2013-09-26 9 views
0

Я не могу понять поведение combobox.Исходное значение ComboBox SelectedItem не из ItemsSource

У меня есть вид редактирования для редактирования существующих данных заказа. Вот мой VM некоторой части данных Order:

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

Описание. Заказ поступает из базы данных репозиторием, _customersListProviderService также получает всех клиентов из базы данных. Я знаю, что, возможно, это может быть сделано лучше, но дело не в этом.

И ... проблема есть. После загрузки окна у моего combobox есть заполненный набор элементов (выпадающий список не пуст), но значение не задано (его пробел). Проверка SelectedItem по результатам кода с нулевым значением. Я много читал и узнал, что вы не можете установить SelectedItem из combobox в элемент, который не находится в ItemsSource.

Хорошо, мой обходной путь, чтобы изменить поглотитель клиентов к:

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

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

теперь он работает, но это не выглядит хорошо для меня.

Есть ли лучшее решение?

+0

Вы также можете переопределить 'Equals()' и 'GetHashCode()' в своих сущностях и вернуть 'Id.Equals()' и 'Id.GetHashCode()' соответственно –

+0

@HighCore, ваше решение для меня самое лучшее , К сожалению, я не могу отметить это как ответ, так как это комментарий. Не могли бы вы переписать его? – GrzegorzM

+1

Очень приятное обходное решение для ситуаций, когда вам нужно показать значение ComboBox, которое отсутствует в ItemSource: [WPF Customized ComboBox с фантомным значением] (http://www.codearsenal.net/2014/11/wpf-customized-phantom-combobox .html) –

ответ

3

вы можете переопределить Equals() и GetHashCode() в ваших лицах и return Id.Equals() и Id.GetHashCode() соответственно

0

Возможно добавление SelectedValuePath = «Name» в вашей XAML, как показано ниже поможет

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

Создать ViewModel с обоими наборами данных, которые нужно установить, чтобы т.е. заполнить ComboBox и запись. Я буду использовать Клиент и год для удобства.

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 присваивается страница Datacontext, и я привязываю это к Combobox.

Комбобокс заполнен Itemsource и Displaymember с помощью списка моделей Year из моей модели Viewmodel. Описание - это просто строка, обозначающая 1999, 2000 или любой другой.

Выбранное значение привязано к внешнему ключу года в записи Customer также в ViewModel. SelectedValuePath - волшебный ингредиент, который связывает 2 вместе. Таким образом, идентификатор представляет идентификатор года, но будет привязан к поле UserID клиента и задан значением идентификатора Combobox.

Надеюсь, что это ясно?!?!?!

0

Я надеюсь, что это будет работать:

Проверьте Customer, уже переплетен другой контроль. Если это так, удалить все остальные привязки, которые включают Customer.

У меня была та же проблема, что и свойство IsChecked CheckBox было также привязано к viewModel, но с помощью конвертера, чтобы проверить, является ли оно нулевым или нет. Я изменил его привязку к логическому, и проблемы больше не было.

2

я просто был аналогичная проблема внутри UWP приложения. Я привязывался к массиву строк.

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

Проблема решена, когда я изменил ItemsSource, чтобы быть перед SelectedItem:

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

Только в случае, если кто-то имеет такой же вопрос.

Смежные вопросы