过滤的Combobox ItemsSource绑定问题

时间:2014-09-15 16:37:23

标签: c# wpf xaml binding

我正在尝试做什么:
我有2个组合框,一个“常规”组合和一个可过滤组合。在可过滤的组合框ItemsSource上绑定到第一个组合框SelectedItem的属性。
下面是一些XAML来演示这种关系(我删除了一些属性):

<ComboBox Name="cbx_poche" ItemsSource="{Binding DataContext.ListePoches, ElementName=Main}" SelectedItem="{Binding PocheCible}" />
<controls:FilteredComboBox ItemsSource="{Binding SelectedItem.SupportsEligibles, ElementName=cbx_poche}" SelectedItem="{Binding Support}" />

FilteredComboBox是来自ComboBox的派生类,受到这些文章的启发:Building a Filtered ComboBox for WPF / WPF auto-filtering combo

用户可以输入组合框并过滤列表以显示匹配的项目。组合框的默认行为是不合需要的(它会自动完成用户输入的内容),这就是它的派生原因。

上面的那些组合框是ItemsControl元素,因为我需要为特定集合中的每个项目都有一行。组合框的SelectedItem属性绑定到此集合中的项目。

结果:
Combobox demo

问题:
它工作得很好......只要你没有在第一个组合框中选择相同的项目(如上例所示:如果我键入一些与上面的组合不匹配的文本,它将被重置)。登记/> 只要几个FilteredComboBox链接到第一个组合框中的相同项目(因此绑定到SelectedItem.SupportsEligibles),在FilteredComboBox中键入文本就会过滤这两个列表。

我知道为什么会这样,我不知道如何解决它。所以我尝试了两件事:

代码1(当前代码): 问题是代码使用列表中的默认视图,因此绑定到此列表的所有控件都将应用相同的过滤器:

protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
    if (newValue != null)
    {
        if (ItemsSourceView != null)
            ItemsSourceView.Filter -= this.FilterPredicate;

        ItemsSourceView = CollectionViewSource.GetDefaultView(newValue);
        ItemsSourceView.Filter += this.FilterPredicate;
    }

    base.OnItemsSourceChanged(oldValue, newValue);
}

代码2: 所以我(天真)的想法是从绑定视图中获取本地视图。我很适合过滤,但打破了绑定(更改第一个组合中的选定项目不会在第一次通过后更新列表)

protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
    if (newValue != null && newValue != ItemsSourceView)
    {
        if (ItemsSourceView != null)
            ItemsSourceView.Filter -= this.FilterPredicate;

        ItemsCollectionViewSource = new CollectionViewSource { Source = newValue };
        ItemsSourceView = ItemsCollectionViewSource.View;
        ItemsSourceView.Filter += this.FilterPredicate;
        this.ItemsSource = ItemsSourceView; // Breaks the binding !!
    }

    base.OnItemsSourceChanged(oldValue, newValue);
}

我被困在这里。
我正在寻找一些事件或Binding类,我可以用来通知绑定更改,以便更新视图。或者可以在不必更改ItemsSource的情况下应用视图

1 个答案:

答案 0 :(得分:0)

我最终使用了相当蹩脚的解决方法,因此我仍然对智能答案感兴趣。

对于感兴趣的人:我添加了另一个类似的ItemsSource2依赖属性(仍然没有找到一个好名字),我在其上绑定了我的项目列表,而不是原始的ItemsSource

当此项目来源更改时,控件将获得一个新的CollectionView(不是默认值)并将其设置为&#34;标准&#34; ItemsSource
控件的其他元素保持相同(类似于链接文章中的代码)。

public static readonly DependencyProperty ItemsSource2Property =
   DependencyProperty.Register(
   "ItemsSource2",
   typeof(IEnumerable),
   typeof(FilteredComboBox),
   new UIPropertyMetadata((IEnumerable)null, new PropertyChangedCallback(OnItemsSource2Changed)));

[Bindable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IEnumerable ItemsSource2
{
    get { return (IEnumerable)GetValue(ItemsSource2Property); }
    set
    {
        if (value == null)
        {
            ClearValue(ItemsSource2Property);
        }
        else
        {
            SetValue(ItemsSource2Property, value);
        }
    }
}

private static void OnItemsSource2Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var ic = (FilteredComboBox)d;
    var oldValue = (IEnumerable)e.OldValue;
    var newValue = (IEnumerable)e.NewValue;

    if (newValue != null)
    {
        //Prevents the control to select the first item automatically
        ic.IsSynchronizedWithCurrentItem = false;

        var viewSource = new CollectionViewSource { Source = newValue };
        ic.ItemsSource = viewSource.View;
    }
    else
    {
        ic.ItemsSource = null;
    }
}