What should the converter parameter be for this binding

狂风中的少年 提交于 2019-12-20 19:36:58

问题


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:


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>



回答2:


Another way is making your converter inherit from DependencyObject (or FrameworkElement). This allows you to declare dependency properties, making it possible to set its values from XAML, even a Binding.

Example: A converter to multiply a value specifing the factor, which is obtained from a property (FactorValue) in a custom control (MyControl).

The converter:

public class MyConverter : DependencyObject, IValueConverter
{
    // The property used as a parameter
    public double Factor
    {
        get { return (double) GetValue(FactorProperty); }
        set { SetValue(FactorProperty, value); }
    }

    // The dependency property to allow the property to be used from XAML.
    public static readonly DependencyProperty FactorProperty =
        DependencyProperty.Register(
        "Factor",
        typeof(double),
        typeof(MyConverter),
        new PropertyMetadata(1.15d));

    #region IValueConverter Members

    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // Use the property in the Convert method instead of "parameter"
        return (double) value * Factor;
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Use in XAML:

<MyConverter x:Key="MyConv"
             Factor={Binding ElementName=MyControl, Path=FactorValue}
/>

So, you can now declare a dependency property for each parameter you need in your converter and bind it.




回答3:


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} }}"
                      />



回答4:


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...



来源:https://stackoverflow.com/questions/377841/what-should-the-converter-parameter-be-for-this-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!