如何绑定多个 ComboBox 的 ItemsSoure 相互连接

How can I bind many ComboBox's ItemsSoure Connected to each other

我有三个组合框。三个绑定相同的 ItemsSource.

这个 ItemsSouce 类型是 Dictionary<string, Dictionary<CustomKey, CustomClass>>

自定义键

public struct CustomKey<T1,T2> // T1, T2 is string
{
    public readonly T1 Symbol;
    public readonly T2 Column;
    public CustomKey(T1 key1, T2 key2) { Symbol = key1; Column = key2; }
}

自定义类

public class CustomClass
{
    public string Value{get;set}
}

First. FirstComboBox的ItemsSoure是Dictionary.Keys

Second. 我想设置 Second ComboBox 的 Items Source 是 FirstComboBox 的 SelectedItems.
像这样 Dictionary[FirstComboBox.SelectedItem]。按键 T1

Third. ThirdComboBox 的 ItemsSource Dictionary[FirstComboBox.SelectedItem].Keys T2

最后一个。
这是我的代码...
// Source.GetNames 是 ItemsSource.Keys.ToList();

 protected virtual FrameworkElement CreateAutoCompleteComboBoxControl(PropertyItem property)
    {
        var c = new AutoCompleteComboBox();
        ContinuityBindablePropertyItem cbp = (property as ContinuityBindablePropertyItem); // cbp is First ComboBox SelectedItem Descriptor. but i don't know how to use...

        if (property.DisplayName == "Sheet") // First ComboBox
        {
            c.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Source.GetSheetNames");
        }
        else if (property.DisplayName == "TestName") // Second ComboBox
        {
            c.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Source.GetSheetNames");
        }
        else if (property.DisplayName == "Symbol") // Third ComboBox
        {
            c.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Source.GetSheetNames");
        }

        c.SetBinding(ComboBox.TextProperty, property.CreateBinding());
        return c;
    }

请帮助我。 我英语说得不好。希望你明白。

谢谢。


编辑 改变方法。

 protected virtual FrameworkElement CreateAutoCompleteComboBoxControl(PropertyItem property)
    {
        StackPanel s = new StackPanel();
        var c1 = new AutoCompleteComboBox { Name = "c1", DisplayMemberPath = "Key", IsEditable = property.IsEditable, ItemsSource = property.ItemsSource, VerticalContentAlignment = VerticalAlignment.Center };
        var c2 = new AutoCompleteComboBox { IsEditable = property.IsEditable, ItemsSource = property.ItemsSource, VerticalContentAlignment = VerticalAlignment.Center };
        var c3 = new AutoCompleteComboBox { IsEditable = property.IsEditable, ItemsSource = property.ItemsSource, VerticalContentAlignment = VerticalAlignment.Center };

        c1.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Source") { Source = MappingService.Instance, Mode = BindingMode.OneWay });
        c2.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Values") {  Source = c1.SelectedItem, Mode = BindingMode.OneWay });
        c3.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("SelectedItem.Values") { ElementName = c1.Name, Mode = BindingMode.OneWay });

        c1.SetBinding(ComboBox.TextProperty, property.CreateBinding());
        c2.SetBinding(ComboBox.TextProperty, property.CreateBinding());
        c3.SetBinding(ComboBox.TextProperty, property.CreateBinding());

        s.Children.Add(c1);
        s.Children.Add(c2);
        s.Children.Add(c3);
        return s;
    }

我尝试绑定路径 'Values'、'Value'、'SelectedItem.Value'、'SelectedItem.Values、将源更改为 C1.SelectedItem 或元素名称 = c1...

但是没用

编辑
添加图像。

我对您正在尝试做的事情感到有点困惑,我想我需要更多的代码或示例来理解它。但我会尝试解决一些问题。另外,我习惯了xaml,所以你可能要补上绑定代码的空缺:

First. FirstComboBox's ItemsSoure is Dictionary.Keys

只是为了检查一下,这是有效的吗?

Second. I want to set Second ComboBox's Items Source is FirstComboBox's SelectedItems. like this Dictionary[FirstComboBox.SelectedItem].Keys T1

Third. ThirdComboBox's ItemsSource Dictionary[FirstComboBox.SelectedItem].Keys T2

这两个本质上是同一个问题,你想绑定到Dictionary.Keys,但是有一个组合框显示T1,另一个显示T2?好的,与其尝试将 ComboBox 直接绑定到 Dictionary[FirstComboBox.SelectedItem].Keys T1,我建议使用以下两种方法之一。

1.使用多绑定转换器。 您的第一个复选框的 ItemsSource 将绑定到一个字符串列表。它的 SelectedItem 将是一个字符串,它是 Dictionary>.

的键

您可以将键和字典都传递给多绑定转换器,并将其 return 字典的键作为列表或数组,如下所示:

public class MyDictionaryValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //first item is our key
        string key = values[0] as string;

        //second item is our dictionary
        Dictionary<string, Dictionary<CustomKey, CustomClass>> dictionary = values[1] as Dictionary<string, Dictionary<CustomKey, CustomClass>>;

        //pass our value to be bound to
        return dictionary[key].Keys.ToList();
    }
}

你知道如何在代码中设置转换器绑定吗?可能需要研究多重绑定,我只在 xaml.

做过

2。您也可以使用中间属性执行此操作 您不必直接绑定到所有内容,您可以在数据对象中创建一个 属性,如下所示:

    public class DataContextThatContainsYourDictionary : INotifyPropertyChanged
{
    //notifying property that is bound to ItemsSource in the first Combobox
    public Dictionary<string, Dictionary<CustomKey, CustomClass>> MyDictionary { get... }

    //This is the string that's bound to SelectedItem in the first ComboBox
    public string SelectedKey
    {
        get
        {
            return selectedKey;
        }
        set
        {
            //standard notify like all your other bound properties
            if (selectedKey != value)
            {
                selectedKey = value;
                //when this changes, our selection has changed, so update the second list's ItemsSource
                SelectedKeys = MyDictionary[SelectedKey].Keys.ToList();
                NotifyPropertyChanged("SelectedKey");
            }
        }
    }

    //an "intermediatary" Property that's bound to the second Combobox, changes with the first's selection
    public List<CustomKey> SelectedKeys { get ... }

这两个结果相同,您最终会将组合框绑定到一个列表。然后,您可以将 DisplayMemberPath 设置为第一个复选框的 T1 或第二个复选框的 T2。

尝试像下面这样设置绑定:您可能还需要为其他两个组合框设置 DisplayMemberPath,具体取决于您要在其中显示的属性。

 var c1 = new AutoCompleteComboBox { Name = "c1", DisplayMemberPath = "Key", IsEditable = property.IsEditable, VerticalContentAlignment = VerticalAlignment.Center };
 var c2 = new AutoCompleteComboBox { IsEditable = property.IsEditable, VerticalContentAlignment = VerticalAlignment.Center };
 var c3 = new AutoCompleteComboBox { IsEditable = property.IsEditable, VerticalContentAlignment = VerticalAlignment.Center };

 c1.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Source") { Source = MappingService.Instance, Mode = BindingMode.OneWay });
 c2.SetBinding(ItemsControl.ItemsSourceProperty, new Binding() { Path = new PropertyPath("SelectedItem.Value.Keys"), ElementName = c1.Name, Mode = BindingMode.OneWay });
 c3.SetBinding(ItemsControl.ItemsSourceProperty, new Binding() { Path = new PropertyPath("SelectedItem.Value.Values"), ElementName = c1.Name, Mode = BindingMode.OneWay });