ComboBox SelectedItem初始值不是来自ItemsSource

时间:2013-09-26 15:13:30

标签: wpf mvvm binding combobox selecteditem

我无法理解组合框的行为。

我有一个编辑视图来编辑现有的订单数据。这是订单数据某些部分的VM:

public class OrderDataViewModel : ViewModelBase, IOrderDataViewModel
{
    private readonly ICustomersListProviderService _customersListProviderService;
    private readonly Order _order;

    public OrderDataViewModel(Order order, ICustomersListProviderService customersListProviderService)
    {
        Assign.IfNotNull(ref _order, order);
        Assign.IfNotNull(ref _customersListProviderService, customersListProviderService);
    }

    public DateTime CreationDate
    {
        get { return _order.CreationDate ?? (_order.CreationDate = DateTime.Now).Value; }
        set
        {
            if (_order.CreationDate == value) return;

            _order.CreationDate = value;
            OnPropertyChanged();
        }
    }

    public Customer Customer
    {
        get { return _order.Customer; }
        set
        {
            if (_order.Customer == value) return;

            _order.Customer = value;
            OnPropertyChanged();
        }
    }


    private IList<Customer> _customersList;
    public IList<Customer> CustomersList
    {
        get { return _customersList ?? (_customersList = _customersListProviderService.GetAllCustomers().ToList()); }
    }
}

和XAML绑定:

 <ComboBox Grid.Row="2" Grid.Column="1"
                        SelectedItem="{Binding OrderDataViewModel.Customer}"
                        DisplayMemberPath="Name"
                        ItemsSource="{Binding OrderDataViewModel.CustomersList}"
                        />

描述。订单来自Repository的数据库,_customersListProviderService也从数据库中获取所有客户。我知道也许它可以做得更好,但这不是问题的关键。

而且......问题是。加载窗口后,我的组合框已填充项目集合(下拉列表不为空)但未设置该值(其空白)。通过代码隐藏结果​​检查SelectedItem为null。我读了很多,发现你不能将组合框的SelectedItem设置为不在ItemsSource中的项目。

好的,我的解决方法是将Customer getter更改为:

public Customer Customer
        {
            get
            { return CustomersList.Single(c => c.Id == _order.Customer.Id); }
            set
            {
                if (_order.Customer == value) return;

                _order.Customer = value;
                OnPropertyChanged();
            }
        } 

现在它有效,但对我来说看起来不太好。

有没有更好的解决方案?

5 个答案:

答案 0 :(得分:4)

您可以覆盖实体中的Equals()GetHashCode()以及return Id.Equals()Id.GetHashCode()

答案 1 :(得分:2)

我在 UWP应用中遇到了类似的问题。我绑定了一个字符串数组。

<ComboBox SelectedItem="{Binding Carrier, Mode=TwoWay}" ItemsSource="{Binding Carriers}" />

当我将ItemsSource更改为SelectedItem:

之前,问题解决了
<ComboBox ItemsSource="{Binding Carriers}" SelectedItem="{Binding Carrier, Mode=TwoWay}" />

以防万一有类似问题。

答案 2 :(得分:0)

或许将SelectedValuePath =“Name”添加到您的xaml(如下所示)将有助于

 <ComboBox Grid.Row="2" Grid.Column="1"
                    SelectedItem="{Binding OrderDataViewModel.Customer}"
                    DisplayMemberPath="Name"
                    ItemsSource="{Binding OrderDataViewModel.CustomersList}"
                    SelectedValuePath="Name"
                    />

答案 3 :(得分:0)

使用您需要的两组数据创建一个ViewModel,即设置为填充ComboBox和Record。为方便起见,我将使用客户和年份。

class CustomerDetailsViewModel
{
    public CustomertModel CutomerModel { get; set; }
    public YearListModel YearList { get; set; }

    public CustomerDetailsViewModel(CustomerModel _CustomerModel)
    {
        CustomerModel = _CustomerModel;
        YearList = new YearListModel();
    }
}

所以我在组合框中填写了多年的清单,并且我已经选择了客户记录。

<ComboBox x:Name="cbCustomerDetailsYear" Margin="128,503,0,0" 
                      DataContext="{Binding DataContext,
                                    ElementName=CustomerDetailsPage}"
                      ItemsSource="{Binding YearList.Years, Mode=OneWay}"
                      DisplayMemberPath="Description"
                      SelectedValue="{Binding CustomerModel.YearID}"
                      SelectedValuePath="id" />

将viewmodel分配给Page Datacontext,然后将其绑定到Combobox。

使用我的Viewmodel中的Year model列表,使用Itemsource和Displaymember填充组合框。描述只是一个字符串,说1999年,2000年或其他什么

SelectedValue也绑定到ViewModel中Customer记录中的Year外键。 SelectedValuePath是将2绑定在一起的神奇成分。因此id表示年份的id,但将绑定到客户YearID字段并由Combobox id值设置。

希望这很清楚?!?!?!

答案 4 :(得分:0)

我希望这会奏效:

检查Customer是否已绑定到另一个控件。如果是这样,会删除涉及Customer 的所有其他绑定。

我遇到了同样的问题,其中CheckBox的IsChecked属性也被绑定到viewModel,但是使用转换器检查它是否为null。我将其绑定更改为布尔值,问题就不复存在了。