WPF中绑定参数的哲学思考

时间:2014-04-26 19:07:33

标签: c# wpf binding valueconverter

所以我正在尝试构建一个项目,允许用户在表单左侧的文本框中键入一些文本,这将从我的数据源列表中过滤掉可用的项目。

<Label Content="Enter item name below"></Label>
<TextBox Name="SearchTermTextBox" TabIndex="0" Text="" />

我的印象是我可以绑定到数据源列表然后使用转换器来过滤掉与字符串不同的项目。

<ListBox DataContext="{Binding Colors}">
   <ListBox.ItemsSource>
     <MultiBinding Converter="{StaticResource FilterTextValueConverter}" ConverterParameter="{Binding ElementName=SearchTermTextBox, Path=Text}" />
   </ListBox.ItemsSource>
   <ListBox.ItemTemplate>
       //etc...
    </ListBox.ItemTemplate>
</ListBox>

但是,除非使用称为依赖项属性的内容,否则无法绑定到converterparameter中的elementname。

编辑:看到我已经与上面的代码混淆了,这里是我想要绑定的转换器:

public class FilterTextValueConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var trackedColors = value as List<Colors>;
        if (trackedColors != null)
            return (trackedColors).Where(item => item.ColorName.Contains(parameter.ToString())).ToList();

        return null;
    }

    public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


public class Colors
{
    public String ColorName;
    public String Description;
}

我的方法有什么问题?很显然,我对WPF众神感到愤怒,因为这是一个相当简单的操作,但我原则上被拒绝了。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

使用转换器进行简单绑定就可以了,不需要MultiBinding。

<ListBox ItemsSource="{Binding Path=Text, ElementName=SearchTermTextBox,
                          Converter="{StaticResource FilterTextValueConverter}">
   ......
</ListBox>

假设 FilterTextValueConverter 正在实施 IValueConverter ,您可以从传递给Convert方法的值访问文本。

public class FilterTextValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        string text = value.ToString(); // TEXT for textBox can be accessed here.
        return new List<string>(); // Return filtered list from here.
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
                              System.Globalization.CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

<强>更新

如果您想将多个绑定传递给转换器,请使用 IMultiValueConverter ,因为 ConverterParameter 不是Dependency属性,因此无法绑定。

XAML

<ListBox DataContext="{Binding Colors}">
    <ListBox.ItemsSource>
        <MultiBinding Converter="{StaticResource FilterTextValueConverter}">
            <Binding/>
            <Binding ElementName="SearchTermTextBox" Path="Text"/>
        </MultiBinding>
    </ListBox.ItemsSource>
</ListBox>

转换器

public class FilterTextValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, 
                          System.Globalization.CultureInfo culture)
    {
        var trackedColors = values[0] as List<Colors>;
        if (trackedColors != null && !String.IsNullOrEmpty(values[1].ToString()))
            return (trackedColors).Where(item => 
                   item.ColorName.Contains(values[1].ToString())).ToList();

        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes,
                                object parameter,
                                System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

答案 1 :(得分:0)

在接受的答案发布并为我工作后,我继续深入研究这个问题。我发现,包装控件是一项相当简单的任务,你试图从中获取新的依赖属性以允许正确的绑定。

我不会接受我自己对此决定的答案,但这似乎(在我的业余观点中)似乎比添加转换器更优雅的解决方案,尽管有点复杂:

请注意,这是针对文本框的caretindex属性的新依赖关系,而不是关于绑定的原始问题,但它只需要一些智能重命名才能使其正常工作;)。

    public class TextBoxDependencyWrapper : TextBox
    {
        public static readonly DependencyProperty CaretIndexProperty = DependencyProperty.Register(
            "CaretIndex", typeof (int), typeof (TextBoxDependencyWrapper), new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CaretIndexChanged ));

        protected override void OnKeyUp(KeyEventArgs e) //Event that changes the property we're trying to track
        {
            base.OnKeyUp(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyDown(KeyEventArgs e) //Event that changes the property we're trying to track
        {
            base.OnKeyDown(e);
            CaretIndex = base.CaretIndex;
        }

        public new int CaretIndex
        {
            get { return (int) GetValue(CaretIndexProperty); }
            set { SetValue(CaretIndexProperty, value); }
        }
    }