这个绑定的转换器参数应该是什么?

11
我正在尝试实现一个WPF用户控件,使用转换器将文本框绑定到双精度列表。如何设置用户控件的实例作为转换器参数?
下面是该控件的代码。
谢谢。
<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>
4个回答

11

另一种方法是使您的转换器继承自DependencyObject(或FrameworkElement)。这样可以声明依赖属性,使其可以从XAML中设置其值,甚至可以使用绑定。

例如:一个转换器,将一个值乘以特定的因子,该因子是从自定义控件(MyControl)中的属性(FactorValue)中获取的。

转换器示例:

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
}

在XAML中使用:

<MyConverter x:Key="MyConv"
             Factor={Binding ElementName=MyControl, Path=FactorValue}
/>
所以,现在你可以为你的转换器声明每个需要的参数的依赖属性并绑定它们。

8

这些参数是您的转换器所需的常量。要向转换器提供对象实例,您可以使用MultiBinding。

注意:为使此解决方案起作用,您还需要修改转换器以实现IMultiValueConverter而不是IValueConverter。幸运的是,所涉及的修改非常少。您将可以为您的转换器添加一个验证,以验证提供给转换器的值的数量,在您的情况下是2个。

<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
当然可以将对象引用作为转换器参数传递 - 确实,它必须被视为常量,因为WPF没有提供重新绑定转换器参数的方法,但这并不意味着它不能是对象引用! - Daniel Paull
@Frederic:当我尝试这段代码时,出现了一个错误。"属性 'Converter' 不支持类型为 'BaySizeControl.BayListtoStringConverter' 的值"。我的转换器需要修改才能与此解决方案配合使用吗? - David Turvey
@Daniel Paull:听起来可能是可行的。你能详细说明一下吗?谢谢。 - David Turvey
@Dave - 请看一下我的博客,其中介绍了如何使用嵌入式Python在XAML/WPF中实现John Conway的生命游戏(http://www.thinkbottomup.com.au/site/blog/Game_of_Life_in_XAML_WPF_using_embedded_Python)。在“棋盘视图”部分,我将对象数组作为转换器参数传递。希望这能有所帮助。 - Daniel Paull

1

我也遇到了同样的问题,但是我不能使用MultiBindings,因为我需要正确实现ConvertBack方法。这是我最终为CheckBox的IsChecked属性实现的解决方案:

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

我对TemplateBindings(或者说WPF的任何东西)并不是非常熟悉,所以也许这只能在我的CheckBox位于DataTemplate中时才起作用...


最终它将会是一个空的数据上下文。 - Ievgen

1

我会给控件命名,然后使用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>

不行,等等,那样做不起作用,因为ConverterParameter不是一个依赖属性,Binding也不是DependencyObject。使用RelativeSource标记扩展应该可以实现你想要的效果,尽管我没有在其他MarkupExtension中嵌套使用过它 - 也许在这种情况下它表现不佳:

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

我已经尝试过这种方法了。传递的参数是System.Windows.Data.RelativeSource类型,而不是预期的BaySizeTextBox。 - David Turvey
我们不需要使用"self",尝试使用"{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"。 - Daniel Paull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接