筛选后的组合框ItemsSource绑定问题 [英] Filtered Combobox ItemsSource binding issue

查看:36
本文介绍了筛选后的组合框ItemsSource绑定问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What I'm trying to do :
I have 2 comboboxes, a "regular" one, and a filtrable one. On the filtrable combobox ItemsSource is binded to a property of the first combobox SelectedItem.
Here is some XAML to demonstrate the relation (I removed some properties):

<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 派生的类,这些类的灵感来自于这些文章: WPF自动-过滤组合.

The FilteredComboBox is a derived class from ComboBox inspired by those articles : Building a Filtered ComboBox for WPF / WPF auto-filtering combo.

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

The user can type in the combobox and it filters the list to display the items matching. The default behavior of the combobox is NOT desired (it automatically completes what the user types), this is why it's derived.

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

Those comboboxes above are in a ItemsControl element, because I need to have one row for each item in a specific collection. The SelectedItem properties of the comboboxes are binded to the item in this collection.

结果:

问题:
只要您在第一个组合框中没有选择相同的项目,它就可以很好地工作(例如上例:如果我输入的文本与上述组合不匹配,它将被重置).br>一旦几个FilteredComboBox链接到第一个组合框中的同一项目(因此绑定到 SelectedItem.SupportsEligibles ),则在FilteredComboBox中键入文本将过滤两个列表.

The problem :
It works quite well... as long as you don't select the same item in the first combobox (like in the example above : if I type some text that doesn't match the above combo, it will be reset).
As soon as several FilteredComboBox are linked to the same item in the first combobox (so binded to SelectedItem.SupportsEligibles), typing text in the FilteredComboBox filters both lists.

我知道为什么这样做,但不知道如何解决.所以我尝试了两件事:

I know why it does that, I don't know how to fix it. So I tried two things :

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

Code 1 (current code) : The problem is that the code uses the default view on the list, so all controls binded to this list will apply the same filter :

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:所以我的想法是从绑定视图中获取局部视图.我可以很好地进行过滤,但是会破坏绑定(在第一次通过后更改第一个组合中的所选项目并不会更新列表)

Code 2 : So my (naïve) idea was to get a local view from the binded view. I works well for filtering, but breaks the binding (changing the selected item in the first combo doesn't update the list after the first pass)

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而应用视图

I'm stuck here.
I'm looking for some event or Binding class that I could use to be notified of the binding change, in order to update the view. Or maybe getting the view applied without having to change the ItemsSource

推荐答案

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

I ended up using a quite lame workaround, so I'm still interested in smart answers.

对感兴趣的人:我添加了另一个类似的 ItemsSource2 依赖项属性(仍然找不到合适的名称),我在该属性上绑定了我的项目列表,而不是原始的 ItemsSource .

For people interested : I added another similar ItemsSource2 Dependency Property (still didn't find a nice name for it) on which I bind my item list, instead of the original ItemsSource.

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

When this items source is changed, the control gets a new CollectionView (not the default one) and sets it to the "standard" ItemsSource.
The other elements of the control remains identical (similar to the code in the linked articles).

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;
    }
}

这篇关于筛选后的组合框ItemsSource绑定问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆