简体   繁体   English

Wpf组合框选择的项目不起作用

[英]Wpf combobox selected item not working

I have two object: UserDto and RoleDto. 我有两个对象:UserDto和RoleDto。 User has a property which is the RoleDto. 用户拥有RoleDto属性。 In my viewmodel I have the following: 在我的viewmodel中,我有以下内容:

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 提前致谢

This is because the reference of RoleDTO that your UserDTO has, does not match any of the RoleDTOs in Roles collection which you set as ItemsSource of ComboBox . 这是因为您的UserDTO具有的RoleDTO引用与您设置为ComboBox ItemsSourceRoles集合中的任何RoleDTOs都不匹配。

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" />

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. 您可以覆盖对象上的equals属性,以便在项目具有相同数据时返回true。 Then when the combo box box goes to check to make sure your item is in the selection it will find a match. 然后,当组合框框进行检查以确保您的项目在选择中时,它将找到匹配项。

The other way to solve this problem is using Converter on Binding . 解决此问题的另一种方法是使用Converter on Binding when you use binding to bind SelectedItem , WPF will check the reference of SelectedItem against all objects inside ItemsSource property and of course if there was no match, SelectedItem will be empty. 当您使用绑定绑定SelectedItem ,WPF将针对ItemsSource属性中的所有对象检查SelectedItem的引用,当然如果没有匹配, SelectedItem将为空。 using Converter you can tell WPF that how it should match SelectedItem . 使用Converter你可以告诉WPF它应该如何匹配SelectedItem
In this case you just need find SelectedItem among ItemsSource and return it to Binding . 在这种情况下,您只需要在ItemsSource找到SelectedItem并将其返回给Binding so follow these steps: 请按照以下步骤操作:
1- Create a class and implement IValueConverter . 1-创建一个类并实现IValueConverter It has two methods: Convert and ConvertBack 它有两种方法: ConvertConvertBack
2- for Convert method do something like this: 2- for Convert方法做这样的事情:

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 Converter on your Binding like this: 3-在Binding上使用此Converter ,如下所示:

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 XAML you can not pass ConverterParameter like this, instead you should create a static list and use that as ItemsSource or use MultiBinding to pass your ConverterParameter using a trick. 注意 :如果你想从XAML进行绑定,你不能像这样传递ConverterParameter ,而应该创建一个static列表并将其用作ItemsSource或使用MultiBinding来使用技巧传递ConverterParameter here there is a good and simple explanation about it: Binding ConverterParameter 这里有一个很好的简单解释: 绑定ConverterParameter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM