#c# #wpf #mvvm #combobox #inotifypropertychanged
#c# #wpf #mvvm #выпадающий список #inotifypropertychanged #combobox
Вопрос:
Я использую MVVM с библиотеками Galasoft MVVMLight.
У меня есть две модели; каждая имеет логическое свойство и разные свойства одного и того же типа.
public class Model1 : ObservableObject
{
public EnumPair<YesNoInherit> Model1Property
{
get { return _model1Property; }
set
{
_model1Property = value;
Updated = true
RaisePropertyChanged("Model1Property");
}
}
public bool Updated
{
get { return _updated; }
set
{
_updated = value;
RaisePropertyChanged("Updated");
}
}
}
public class Model2 : ObservableObject
{
public EnumPair<YesNoInherit> Model2Property
{
get { return _model2Property; }
set
{
_model2Property = value;
Updated = true
RaisePropertyChanged("Model2Property");
}
}
public bool Updated
{
get { return _updated; }
set
{
_updated = value;
RaisePropertyChanged("Updated");
}
}
}
Тип YesNoInherit — это перечисление, имеющее значения No, Yes и Inherit .
Вот класс EnumPair .
public class EnumPair<T> : ObservableObject where T : struct, IConvertible
{
public T EnumValue
{
get { return _enumValue; }
set
{
if (Type.Equals(value, _enumValue) == false)
{
_enumValue = value;
RaisePropertyChanged();
}
}
}
public string SourceName
{
get { return _sourceName; }
set
{
_sourceName = value;
RaisePropertyChanged();
}
}
}
На мой взгляд, я пытаюсь использовать поле со списком, чтобы позволить пользователю выбрать одно из трех значений enum и, в некоторых случаях, отобразить пользовательский текст. Ресурс «enumComboBoxTemplate» позволяет раскрывающемуся списку ComboBox отображать описания перечислений. Конвертер «inheritanceEnum2Desc» — это то место, где будет применен пользовательский текст. «object1» является экземпляром «Model1».
<ComboBox ItemTemplate=ItemTemplate="{StaticResource enumComboBoxTemplate}"
EnumSource="enums:YesNoInherit">
<ComboBox.Text>
<MultiBinding Converter="{StaticResource inheritanceEnum2Desc}">
<Binding Path="object1.EnumValue"/>
<Binding Path="object1.SourceName"/>
</MultiBinding>
</ComboBox.Text>
</ComboBox>
«Model2» будет использоваться в будущем программировании, использующем аналогичную функциональность, но с другими данными.
Когда я меняю выбор в выпадающем списке, я хочу изменить значение «Обновлено» (с false на true), чтобы я мог включить кнопку в представлении. Похоже, для этого требуется, чтобы класс EnumPair каким-то образом заставил программу выполнить параметр для Model1Property . Поскольку два класса моделей имеют свойства типа EnumPair, я не думаю, что смогу добавить какой-либо код в EnumPair, специфичный для любого класса модели.
Как я могу этого добиться? Я был бы очень признателен за любую помощь.
Комментарии:
1. «»Model2″ будет использоваться в будущем программировании, использующем аналогичную функциональность, но с другими данными». Похоже, вам не следует создавать два отдельных класса, а вместо этого создавать два отдельных экземпляра. Однако я не совсем понимаю вашу точку зрения. Похоже, вам нужен ViewModelLocator для доступа к вашим статическим ViewModels. Пожалуйста, опишите вашу проблему подробнее.
Ответ №1:
В принципе, у вас есть два варианта: либо использовать какую-то шину сообщений для обновления другой модели (у Prism есть EventAggregator
, не уверен насчет MVVMLight), либо заставить оба экземпляра модели пересылать свои свойства в общий источник данных, который уведомляет всех своих пользователей при изменении свойства.
Ответ №2:
Если вы хотите иметь возможность легко переходить из одного класса в другой в будущем, не переписывая весь свой код, вам нужно создать интерфейс, который определяет все то, что объединяет две модели, и оба класса моделей должны реализовать интерфейс. Вы могли бы вызвать интерфейс IModel1
Таким образом, вместо того, чтобы иметь «Model1» в вашей viewmodel, вместо этого у вас будет «IModel1» в вашей viewmodel. Вы могли бы передать тот же объект, который вы передаете сейчас, который имеет тип Model1, потому что он реализует интерфейс IModel1. Когда вы будете готовы переключиться, передайте вместо этого Model2 , и он будет работать без необходимости переписывать что-либо в вашем представлении или viewmodel. Ваши сеттеры могут быть совершенно разными — пока обе модели имеют все методы и свойства, требуемые интерфейсом, все будет в порядке.
С другой стороны, если Model2 точно такой же, как Model1, за исключением того, что в нем есть «дополнительные вещи», вы можете сделать Model2 производным классом, который является производным от Model1.
Поиск в Google по любому из этих терминов должен указать вам на хороший учебник.
Комментарии:
1. если вы имеете в виду переход с Model1 на Model2, я этого не делаю. Model1 находится в одном представлении, а Model2 — в другом представлении. Model1 и Model2 не связаны, кроме того, что каждый класс имеет свойство EnumPair . В одном приложении (App1) его поле со списком привязано к object1 . Model1Property . EnumValue; в другом приложении (App2) его поле со списком привязано к object2 . Model2Property . EnumValue . Если в App1 я изменяю значение combobox, должен выполняться код в параметре для Model1Property; если в App2 я изменяю значение combobox, должен выполняться код в параметре для Model2Property. Это меняет ваш ответ?
2. Да, это меняет ответ. В Model1 и Model2 просто используйте другой код в своем установщике (независимо от того, имеют ли свойства EnumPair одно и то же имя и один и тот же тип или нет.) Зачем вам нужно использовать одну и ту же логику в обоих классах моделей только потому, что они оба имеют один и тот же тип свойства? Это все равно, что сказать, что Window1 и Window2 должны иметь одинаковый заголовок только потому, что у них обоих есть свойство «Title», или что Button1 и Button2 нуждаются в одинаковом поведении OnClick только потому, что у обеих кнопок есть событие «OnClick». С какой реальной проблемой вы столкнулись?