WPF绑定在ComboBox与UserControl列表 [英] WPF Binding in ComboBox with UserControl list

查看:234
本文介绍了WPF绑定在ComboBox与UserControl列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在两个组合框A和B.
A的ItemsSource是自定义列表。和B的ItemsSource是UserControl列表。
手动设置SelectedItem时,组合框可以正常工作,但B组合框UI不显示选定的项目。 (在调试中,SelectedItem的值映射是正确的,但组合框B的UI不更改。)
所有其他结构在A和B之间是相同的。原因是什么?

In two combobox A and B. A's ItemsSource is Custom list. and B's ItemsSource is UserControl list. When manually setting the SelectedItem, A combobox works well, but B combobox UI do not show the selected Item. (In debugging, SelectedItem's value mapping is right, but the combobox B's UI do not be changed.) All the other structure is same between A and B. What is the reason?

MainWindow.xaml

MainWindow.xaml

 ...
<ComboBox ItemsSource="{Binding FruitList}" SelectedItem="{Binding SelectedFruit}"
  DisplayMemberPath="FruitName"  />
<Button Content="Button" HorizontalAlignment="Left"  
VerticalAlignment="Top" Width="75" Click="Button_Click"/>

<ComboBox ItemsSource="{Binding UserControlList}" SelectedItem="{Binding SelectedUserControl}" DisplayMemberPath="ItemName"  />
    <Button Content="Button" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="75" Click="Button_Click2"/>
</Grid>

MainWindow.xaml.cs

MainWindow.xaml.cs

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        FruitList.Add(f1);
        FruitList.Add(f2);
        FruitList.Add(f3);

        UserControlList.Add(u1);
        UserControlList.Add(u2);
        UserControlList.Add(u3);

    }

    Fruit f1 = new Fruit { FruitName = "Apple" };
    Fruit f2 = new Fruit { FruitName = "Banana" };
    Fruit f3 = new Fruit { FruitName = "Lemon" };

    MyUserControl u1 = new MyUserControl { ItemName = "Apple" };
    MyUserControl u2 = new MyUserControl { ItemName = "Banana" };
    MyUserControl u3 = new MyUserControl { ItemName = "Lemon" };

    ObservableCollection<Fruit> _FruitList = new ObservableCollection<Fruit>();
    public ObservableCollection<Fruit> FruitList
    {
        get { return _FruitList; }
        set
        {
            _FruitList = value;
            OnPropertyChanged();
        }
    }

    Fruit _SelectedFruit;
    public Fruit SelectedFruit
    {
        get { return _SelectedFruit; }
        set
        {
            _SelectedFruit = value;
            OnPropertyChanged();
        }
    }



    ObservableCollection<MyUserControl> _UserControlList = new ObservableCollection<MyUserControl>();
    public ObservableCollection<MyUserControl> UserControlList
    {
        get
        {
            return _UserControlList;
        }
        set
        {
            _UserControlList = value;
            OnPropertyChanged();
        }
    }
    MyUserControl _SelectedUserControl;
    public MyUserControl SelectedUserControl
    {
        get { return _SelectedUserControl; }
        set
        {
            _SelectedUserControl = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged([CallerMemberName] string caller = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }
    }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.SelectedFruit = f3;
    }

    private void Button_Click2(object sender, RoutedEventArgs e)
    {
        this.SelectedUserControl = u3;
    }
}

public class Fruit
{
    public string FruitName { get; set; }
}

}

UserControl

UserControl

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();

    }

    public string ItemName { get; set; }
}


推荐答案

原因是什么?:

第二个组合框没有显示任何选择的原因是 ComboBox 处理类型 ContentControl 的项目。在只读选择框中,不是用于显示值的 ContentControl ,而是 ContentControl 。由于 UserControl ContentControl ,因此 UserControl 显示在选择框内,因此您丢失了 UserControl 的数据上下文;最后,即使 SelectedItem 包含对仍然具有有效数据的 UserControl 的引用,也会显示一个空字符串上下文。 (据我所知,这种行为是无记录;但你可以看到它的工作原理是这样的,通过检查ComboBox的代码 http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/ComboBox.cs ,尤其是UpdateSelectionBoxItem()方法)。

The reason why the second combo box does not show any selection is that ComboBox handles items of type ContentControl specially. In the read-only selection box, it is not the ContentControl that is used to display the value, but the content of the ContentControl. Since a UserControl is a ContentControl, the content of the UserControl is displayed inside the selection box, and therefore you have lost the data context of the UserControl; in the end, an empty string is displayed even though SelectedItem contains a reference to the UserControl that still has a valid data context. (As far as I know this behavior is undocumented; but you can see that it works like this by examining the ComboBox's code on http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/ComboBox.cs, especially the UpdateSelectionBoxItem() method).

通过在第二个ComboBox上设置 IsEditable =True,您可以看到,如果组合框没有只读选择框。

By setting IsEditable="True" on the second ComboBox, you can see that everything works fine if the combo box has no read-only selection box.

因此,你通常应该避免添加UI元素到组合框,特别是如果你使用 DisplayMemberPath

Therefore, you generally should avoid adding UI elements to combo boxes, especially if you are using the DisplayMemberPath property, i.e. if you never want to actually display the UI element.

推荐以非标准外观显示ComboBox项目的方法(例如:

The recommended way to display ComboBox items with non-standard appearance (e.g. with UserControls) is described in the answer of @nit.

但是,如果你坚持传递一个 UserControl 项目列表到ComboBox,您可以删除 DisplayMemberPath ,并使用如下所示:

If you, however, insist on passing a UserControl item list to the ComboBox, you might remove DisplayMemberPath and use something like this:

<ComboBox ItemsSource="{Binding UserControlList}" SelectedItem="{Binding SelectedUserControl}" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemName}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

此外,在UserControl的构造函数中,必须放置此行:

Furthermore, in the constructor of your UserControl, you must place this line:

((FrameworkElement) Content).DataContext = this;

这是必要的,以确保在只读选择框中提供正确的数据上下文,它只包含用户控件的内容,而不是用户控件本身。

This is necessary to make sure that the correct data context is available in the read-only selection box, which only contains the content of the user control, not the user control itself.

请注意,对于上面的例子,下拉列表只包含文本项目名称),但选择框将包含完全呈现的用户控件。

Please note, that with the above example, the drop-down list contains text only (i.e. the item names), but the selection box will contain the fully rendered user control.

这篇关于WPF绑定在ComboBox与UserControl列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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