views:

8771

answers:

3

I am trying to implement a wpf user control that binds a text box to a list of doubles using a converter. How can i set the instance of user control to be the converter parameter?

the code for the control is shown below

Thanks

<UserControl x:Class="BaySizeControl.BaySizeTextBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:local="clr-namespace:BaySizeControl"
    >
    <UserControl.Resources>
        <local:BayListtoStringConverter x:Key="BaySizeConverter"/>
    </UserControl.Resources>
    <Grid>

        <TextBox  Name="Textbox_baysizes" 
                  Text="{Binding RelativeSource={RelativeSource self},
                                Path=Parent.Parent.BaySizeItemsSource, 
                                Converter={StaticResource BaySizeConverter}}"
                  />
    </Grid>
</UserControl>
+1  A: 

The parameters are for constants needed by your converter. To provide an object instance to your converter, you can use MultiBinding.

Note: For this solution to work, you also need to modify your converter to implement IMultiValueConverter instead of IValueConverter. Fortunately, the modifications involved are fairly little. You will can add a validation for the number of values provided to your converter, 2 in your case.

<TextBox Name="Textbox_baysizes">
    <TextBox.Text>
        <MultiBinding Converter="{StaticResource BaySizeConverter}">
            <Binding RelativeSource="{RelativeSource self}" Path="Parent.Parent.BaySizeItemsSource"/>
            <Binding ElementName="Textbox_baysizes"/>
        </MultiBinding>
    </TextBox.Text>
</TextBox>
Frederic
Of course you can pass object reference as converter parameters - true that it must be thought of as a constant as WPF offers no way to have the converter parameter re-bind once set, but that doesn't mean that it can't be an object reference!
Daniel Paull
@Frederic: I get an error when trying this code. "Property 'Converter' does not support values of type 'BaySizeControl.BayListtoStringConverter'". Will my converter require modification to work with this solution?
Dave Turvey
@Daniel Paull: That sounds like it might work. could you please elaborate on this? thanks
Dave Turvey
@Dave - have a look at my blog on "John Conway's Game of Life in XAML/WPF using embedded Python" (http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python). In the "A View of the Board" section I pass an array of objects as the converter parameter. Hope that helps.
Daniel Paull
A: 

I would name the control and then bind using ElementName:

<UserControl x:Class="BaySizeControl.BaySizeTextBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    xmlns:local="clr-namespace:BaySizeControl"
    Name="Foobar"
    >
    <UserControl.Resources>
        <local:BayListtoStringConverter x:Key="BaySizeConverter"/>
    </UserControl.Resources>
    <Grid>

        <TextBox  Name="Textbox_baysizes" 
                  Text="{Binding RelativeSource={RelativeSource self},
                                Path=Parent.Parent.BaySizeItemsSource, 
                                Converter={StaticResource BaySizeConverter,
                                ConverterParameter={Binding ElementName=Foobar} }}"
                  />
    </Grid>
</UserControl>

No, wait, that won't work because the ConverterParameter is not a Dependency Property, nor is the Binding a DependencyObject. A ReleativeSource markup extension should do what you want, though I've not used it nested inside other MarkupExtension - perhaps it is not well behaved in this case:

<TextBox  Name="Textbox_baysizes" 
                      Text="{Binding RelativeSource={RelativeSource self},
                                    Path=Parent.Parent.BaySizeItemsSource, 
                                    Converter={StaticResource BaySizeConverter,
                                    ConverterParameter={RelativeSource self} }}"
                      />
Daniel Paull
I have tried this method already. The parameter that is passed is of type System.Windows.Data.RelativeSource. Not BaySizeTextBox as expected.
Dave Turvey
We're not after "self", try "{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}".
Daniel Paull
A: 

I had the same problem, but I can't use MultiBindings since I need to correctly implement the ConvertBack method. Here is the solution I ended up implementing for a CheckBox's IsChecked property:

<CheckBox>
    <CheckBox.IsChecked>
        <Binding Converter="{StaticResource myConverter}" Path="Value">
            <Binding.ConverterParameter>
                <FrameworkElement DataContext="{TemplateBinding DataContext}" />
            </Binding.ConverterParameter>
        </Binding>
    </CheckBox.IsChecked>
</CheckBox>

I'm not super familiar with TemplateBindings (or anything WPF for that matter), so maybe this only works because my CheckBox is in a DataTemplate...

Nicolas Rousseau-Dupuis