Допустим, мы получили простой класс VM
public class PersonViewModel : Observable
{
private Person m_Person= new Person("Mike", "Smith");
private readonly ObservableCollection<Person> m_AvailablePersons =
new ObservableCollection<Person>( new List<Person> {
new Person("Mike", "Smith"),
new Person("Jake", "Jackson"),
});
public ObservableCollection<Person> AvailablePersons
{
get { return m_AvailablePersons; }
}
public Person CurrentPerson
{
get { return m_Person; }
set
{
m_Person = value;
NotifyPropertyChanged("CurrentPerson");
}
}
}
Достаточно успешно выполнить привязку данных к ComboBox, например:
<ComboBox ItemsSource="{Binding AvailablePersons}"
SelectedValue="{Binding Path=CurrentPerson, Mode=TwoWay}" />
Обратите внимание, что Person имеет Equals
перегружен, и когда я устанавливаю значение CurrentPerson в ViewModel, он вызывает текущее значение элемента combobox для отображения нового значения.
Теперь скажем, что я хочу добавить возможности сортировки в свое представление, используя CollectionViewSource
<UserControl.Resources>
<CollectionViewSource x:Key="PersonsViewSource" Source="{Binding AvailablePersons}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Surname" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</UserControl.Resources>
Теперь привязка источника ссылок combobox будет выглядеть так:
<ComboBox ItemsSource="{Binding Source={StaticResource PersonsViewSource}}"
SelectedValue="{Binding Path=CurrentPerson, Mode=TwoWay}" />
И это будет действительно отсортировано (если мы добавим еще несколько элементов, которые он ясно видел).
Однако, когда мы теперь меняем CurrentPerson
в VM (раньше с явным связыванием без CollectionView он работал нормально) это изменение не отображается в связанном ComboBox.
Я считаю, что после этого, чтобы установить CurrentItem из VM, нам нужно каким-то образом получить доступ к представлению (и мы не перейдем к View from ViewModel в MVVM) и вызовите метод MoveCurrentTo
, чтобы заставить View current currentItem изменить.
Итак, добавив дополнительные возможности просмотра (сортировка), мы потеряли привязку TwoWay к существующей модели viewModel, которая, как мне кажется, не ожидается.
Есть ли способ сохранить привязку TwoWay? Или, может быть, я сделал что-то неправильно.
РЕДАКТИРОВАТЬ: ситуация более сложная, чем может показаться, когда я переписываю средство настройки CurrentPerson следующим образом:
set
{
if (m_AvailablePersons.Contains(value)) {
m_Person = m_AvailablePersons.Where(p => p.Equals(value)).First();
}
else throw new ArgumentOutOfRangeException("value");
NotifyPropertyChanged("CurrentPerson");
}
работает
fine
!
Его ошибочное поведение, или есть объяснение? По некоторым причинам, даже если Equals
перегружен, для него требуется ссылочное равенство.
Я действительно не понимаю, почему для этого требуется ссылочное равенство, поэтому я добавляю bounty для тех, кто может объяснить, почему обычный сеттер не работает, когда метод Equal
перегружен, что может ясно можно увидеть в "фиксирующем" коде, который использует его