Проблема двустороннего связывания с WPF ComboBox с использованием MVVM

У меня есть объект Activity со многими свойствами. Один из них следующий:

public ActivityStatus Status
{
    get { return status; }
    set { status = value; NotifyPropertyChanged("Status"); }
}

Класс ActivityStatus имеет всего два свойства:

public Guid Guid
{
    get { return guid; }
    set { guid = value; NotifyPropertyChanged("Guid"); }
}
public string Name
{
    get { return name; }
    set { name = value; NotifyPropertyChanged("Name"); }
}

и методы Equals :

public override bool Equals(object otherObject)
{
    if (!(otherObject is ActivityStatus)) return false;
    return Equals(otherObject as ActivityStatus);
}
public bool Equals(ActivityStatus otherStatus)
{
    if (!(otherStatus is ActivityStatus) || otherStatus == null) return false;
    return Guid == otherStatus.Guid && Name == otherStatus.Name;
}

У меня есть ActivityViewModel как класс DataContext класса ActivityView . Модель ActivityViewModel имеет свойство Activity типа Activity и, среди прочего, свойство ActivityStatuses типа ObservableCollection ActivityView у меня есть ComboBox , объявленный следующим образом:

<ComboBox ItemsSource="{Binding ActivityStatuses}" 
          SelectedItem="{Binding Activity.Status, Mode=TwoWay}"
          DisplayMemberPath="Name" />

Это позволяет мне выбрать ActivityStatus из ComboBox , и это правильно обновляет свойство Status для Activity в Свойство Activity модели просмотра. Проблема заключается в двусторонней привязке ... при загрузке нового Activity , ComboBox.SelectedItem не обновляется, чтобы показать свойство Activity.Status ценность.

Используя это объявление ComboBox , SelectedItem привязывается к объекту ActivityStatus в Activity , а это другое объект с теми же значениями в свойстве viewmodel ActivityStatuses . Поэтому WPF Framework не считает элементы одинаковыми и не выбирает элемент в ComboBox .

Если я назначу элемент из коллекции с такими же значениями свойству Activity.Status после загрузки каждого Activity , то ComboBox найдет совпадение в своей коллекции ItemsSource и правильно устанавливает свойство SelectedItem , отображающее значение. Я действительно не хочу этого делать, потому что у меня есть много других похожих свойств в классе th Activity , и мне придется повторять этот код везде, где я хочу выполнить двустороннюю привязку к ComboBox es.

Итак, я также попытался выполнить привязку к свойству ActivityStatus.Guid следующим образом:

<ComboBox ItemsSource="{Binding ActivityStatuses}" 
          SelectedValue="{Binding Activity.Status.Guid, Mode=TwoWay}"
          SelectedValuePath="Guid" 
          DisplayMemberPath="Name" />

Это правильно выбрал объект с тем же идентификатором Guid , что и в свойстве Activity.Status из коллекции ComboBox.ItemsSource при загрузке другой ] Активность объектов. Проблема с этим методом заключается в том, что SelectedValue привязан к свойству ActivityStatus.Guid в объекте ActivityStatus , и поэтому при изменении значений в пользовательском интерфейсе только свойство Guid объекта ActivityStatus обновится, оставив имя без изменений. Объект в свойстве Activity.Status не изменяется, за исключением значения его свойства Guid .

Как видите, Я также попытался реализовать метод Equals , поскольку предполагал, что ComboBox будет использовать его для сравнения объектов, но это не имело никакого значения. Итак, наконец, я в растерянности и очень хочу найти простой способ решить эту проблему ... надеюсь, есть простое свойство, которое я пропустил в ComboBox .

Я просто хочу чтобы иметь возможность выбрать элемент в ComboBox и изменить объект Activity.Status соответствующим образом, а также изменить значение свойства Activity.Status из кода и также обновите ComboBox.SelectedItem соответствующим образом. Буду признателен за любой совет.

ОБНОВЛЕНИЕ >>>

Прочитав ответ Уилла, Я попробовал его пример кода в новом решении и увидел, что он работает, как ожидалось. Затем я тщательно изучил его код и увидел, что он такой же, как мой, поэтому снова запустил собственное решение (впервые после этого поста). К моему полному удивлению, это сработало, как и ожидалось, и я не изменил никакого кода!

Это сильно озадачило меня, и я потратил некоторое время, чтобы выяснить, что произошло. Оказывается, проблема была / есть Visual Studio 2010! Я добавил к своим типам данных методы Equals на последнем этапе. По какой-то причине Visual Studio не построила проект типов данных при запуске приложения.

Таким образом, приложение должно было использовать более старый файл DLL, а мои изменения не использовались ... Мне было интересно, почему мои точки останова на Методы Equals никогда не выполнялись. Это привело к моему предположению, что реализация методов Equals не помогла. Visual Studio сегодня ведет себя так же, и именно так я узнал, что произошло.

Я проверил порядок сборки проекта в своем решении, но в нем перечислены типы данных проекта в нужном месте в указанном порядке. Однако при запуске приложения в окне вывода в Visual Studio отображаются загружаемые DLL проекта в другом порядке. Я не уверен, почему при запуске приложения больше не выполняется полная сборка, но, по крайней мере, я знаю, что мне нужно построить этот проект после внесения в него изменений перед запуском приложения.

ОКОНЧАТЕЛЬНОЕ ОБНОВЛЕНИЕ >>>

I только что узнал, почему мой проект типов данных не строился ... Я заглянул в окно Configuration Manager и увидел, что каким-то образом платформа была неправильной для этого проекта, и флажок «Сборка» был снят! Я понятия не имею, как это произошло, но мне очень приятно, что я наконец разобрался в сути проблемы.

12
задан Sheridan 4 June 2011 в 00:17
поделиться