Wpf 组合框所选项目不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23628247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:42:47  来源:igfitidea点击:

Wpf combobox selected item not working

wpfcomboboxselecteditem

提问by Keoki

I have two object: UserDto and RoleDto. User has a property which is the RoleDto. In my viewmodel I have the following:

我有两个对象:UserDto 和 RoleDto。用户有一个属性,它是 RoleDto。在我的视图模型中,我有以下内容:

public UserDto User
    {
        get { return _user; }
        set
        {
            if (_user == value) return;

            _user = value;
            User.PropertyChanged += UserPropertyChanged;
            OnPropertyChanged("User");
        }
    }
    private UserDto _user;

public IEnumerable<RoleDto> Roles { get; set; } //I load all available roles in here

In the view, I want to select the role that the user belongs. This is how I define the combobox in the view:

在视图中,我要选择用户所属的角色。这就是我在视图中定义组合框的方式:

<ComboBox Grid.Row="3" Grid.Column="1" Margin="5" ItemsSource="{Binding Roles}" SelectedItem="{Binding User.Role, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Description" />

If I try to create a new user and select a role from the combobox, it is correctly binded to the user. The problem is that when I load a user that already exists, the role is not displayed in the combobox (even the user has a role defined).

如果我尝试创建一个新用户并从组合框中选择一个角色,它就会正确绑定到该用户。问题是当我加载一个已经存在的用户时,该角色不会显示在组合框中(即使用户定义了角色)。

Any help please?

请问有什么帮助吗?

Thanks in advance

提前致谢

回答by Nitin

This is because the reference of RoleDTOthat your UserDTOhas, does not match any of the RoleDTOsin Rolescollection which you set as ItemsSourceof ComboBox.

这是因为RoleDTO您所UserDTO拥有的引用与您设置为of 的任何RoleDTOsin Roles集合都不匹配。ItemsSourceComboBox

Better define a property on your ViewModel like

更好地在您的 ViewModel 上定义一个属性,例如

    public RoleDTO SelectedRole
    {
        get { return Roles.FirstOrDefault(role => role.Role == User.RoleDto.Role); }
        set { User.RoleDto = value; OnPropertyChanged("SelectedRole"); }
    }

and set it as SelectedItem of you combobox

并将其设置为您的组合框的 SelectedItem

ItemsSource="{Binding Roles}" SelectedItem="{Binding SelectedRole, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Description" />

回答by David

In my opinion the second option on this page is the easiest way.

在我看来,此页面上的第二个选项是最简单的方法。

https://rachel53461.wordpress.com/2011/08/20/comboboxs-selecteditem-not-displaying/

https://rachel53461.wordpress.com/2011/08/20/comboboxs-selecteditem-not-displaying/

You can override the equals property on your object so that it returns true if the items have the same data. Then when the combo box box goes to check to make sure your item is in the selection it will find a match.

您可以覆盖对象上的 equals 属性,以便在项目具有相同数据时返回 true。然后,当组合框开始检查以确保您的项目在选择中时,它将找到匹配项。

回答by Amir Oveisi

The other way to solve this problem is using Converteron Binding. when you use binding to bind SelectedItem, WPF will check the reference of SelectedItemagainst all objects inside ItemsSourceproperty and of course if there was no match, SelectedItemwill be empty. using Converteryou can tell WPF that how it should match SelectedItem.
In this case you just need find SelectedItemamong ItemsSourceand return it to Binding. so follow these steps:
1- Create a class and implement IValueConverter. It has two methods: Convertand ConvertBack
2- for Convertmethod do something like this:

解决此问题的另一种方法是使用Converteron Binding。当您使用 binding 来 bind 时SelectedItem,WPF 将检查SelectedItemItemsSource属性内所有对象的引用,当然如果没有匹配,则为SelectedItem空。使用Converter你可以告诉 WPF 它应该如何匹配SelectedItem
在这种情况下,您只需要 find SelectedItembetweenItemsSource并将其返回到Binding. 所以请按照以下步骤操作:
1- 创建一个类并实现IValueConverter. 它有两种方法:ConvertConvertBack
2- forConvert方法做这样的事情:

public class MySelecteItemBindingConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        var mySelectedItem = value as MySelectedItemType;
        var myItemsSource = parameter as List<MySelectedItemType>;
        var matchedItem = myItemsSource.FirstOrDefault(i=>i.Id == mySelectedItem.Id);
        return matchedItem;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        // Do just like Convert method
    }
}

3- Use this Converteron your Bindinglike this:

3-使用此Converter对您Binding这样的:

var myBinding = new Binding("YourBindingPath");
myBinding.Converter = new MySelectedItemBindingConverter();
myBinding.ConverterParameter = myItemsSource; //this is List<MySelectedItemType> in this example
myCombo.SetBinding(ComboBox.SelectedItemProperty, myBinding);

Note: if you want to do binding from XAMLyou can not pass ConverterParameterlike this, instead you should create a staticlist and use that as ItemsSourceor use MultiBindingto pass your ConverterParameterusing a trick. here there is a good and simple explanation about it: Binding ConverterParameter

注意:如果你想从XAML你做绑定,你不能ConverterParameter像这样传递,相反,你应该创建一个static列表并使用它作为ItemsSource或使用一个技巧MultiBinding来传递你ConverterParameter的。这里有一个很好的简单解释:Binding ConverterParameter