#wpf #events #binding #mvvm #checkbox
#wpf #Мероприятия #привязка #mvvm #флажок
Вопрос:
У меня есть список элементов, отображаемых в виде списка.
<ListView ItemsSource="{Binding ListOfSomeItems}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsReceived}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Теперь мне нужно реализовать 2 пользовательских варианта:
1) Когда пользователь помечает элемент как полученный (флажок установлен) Мне нужно обновить элемент. Как я должен привязать проверенное событие к ICommand в моей ViewModel?
2) Когда пользователь пытается удалить полученный флаг (снимите флажок), всплывающее окно должно быть снабжено возможностью отменить операцию (если кто-то случайно нажал на флажок) или указать причину. Это примечание вместе с элементом, который был снят, должно быть отправлено в другую ICommand в виртуальной машине.
Есть предложения?
Заранее спасибо
ОБНОВЛЕНИЕ: моя ViewModel действительно реализует INoftiyPropertyChanged, но у меня нет свойства для одного элемента. Свойство вложено в сложный класс: что-то вроде Account .Держатели [x].Требования [y].Получено.
Комментарии:
1. Что касается вопроса 1, вам не обязательно использовать ICommand. Когда пользователь устанавливает флажок, в виртуальной машине вызывается метод набора свойств.
2. @jpsstavares — Свойство вложено в сложный класс: что-то вроде Account . Держатели [x].Требования [y]. Получено. Я бы лучше выполнил команду, чем пересек иерархию.
Ответ №1:
- Почему бы просто не привязать команду, которая должна быть представлена ViewModel:
<CheckBox
Command="{Binding ReceivedStatusChangedCommand}"
CommandParameter="{Binding ...IsReceived}"
/>
Затем в обработчике команд вы можете проанализировать переданное значение IsReceived
в качестве командного параметра.
Комментарии:
1. Я хотел бы видеть решение, которое охватывает оба пользовательских случая.
Ответ №2:
Поскольку вы привязываетесь к IsChecked
свойству в своем объекте, вы можете просто прослушать PropertyChanged
событие для этого объекта и вызвать любой метод, который вам нужен, когда он изменяется.
Например,
// Wireup CollectionChanged in Constructor
public MyVMConstructor()
{
ListOfSomeItems = new List<SomeItem>();
ListOfSomeItems.CollectionChanged = ListOfSomeItems_CollectionChanged;
}
// In CollectionChanged event, wire up PropertyChanged event on items
void ListOfSomeItems_CollectionChanged(object sender, CollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach(SomeItem item in e.NewItems)
item.PropertyChanged = SomeItem_PropertyChanged;
}
if (e.OldItems != null)
{
foreach(SomeItem item in e.OldItems)
item.PropertyChanged -= SomeItem_PropertyChanged;
}
}
// In PropertyChanged, if property was IsReceived then verify and update
void SomeItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsReceived")
{
if (MessageBox.Show("Are you sure?", "Confirm", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
var item = sender as SomeItem;
UpdateSomeItem(item.Id, item.IsReceived);
}
}
}
Ответ №3:
Ваша ViewModel должна реализовывать INoftiyPropertyChanged. Просто прослушайте событие PropertyChanged и ответьте на него.
Редактировать
Исходя из структуры вашей ViewModel, если учетная запись должна отвечать требованию a, возможно, лучше всего использовать что-то вроде EventAggregator от Prism или MVVM Light’s Messenger.
Ответ №4:
Решение MVVM было бы:
- Поскольку привязки являются двусторонними, вам не нужно ничего делать, чтобы обновить ваш объект из пользовательского интерфейса. Но если вы хотите, чтобы ваш пользовательский интерфейс обновлялся при изменениях в модели, ваши классы модели должны реализовать
INotifyPropertyChanged
- Я предполагаю, что это было бы сделано в
IsReceived
установщике. Добавьте два поля в свой класс модели.
public string ValidationError
{ get; set; }
public bool HasValidationError
{ get; set; }
Затем создайте всплывающее окно с ошибкой, которая по умолчанию скрыта. Реализуйте INotifyPropertyChanged
в своем классе и привяжите видимость всплывающего окна к HasValidationError
, а сообщение во внутреннем TextBlock
— к ValidationError
.
Комментарии:
1. Есть ли что-то конкретное для этого случая, что это все равно не будет применяться? Та же логика должна быть жизнеспособной. Если есть что-то, что делает это очень сложным, вам следует подумать о создании ViewModel, который выполнял бы любые необходимые вычисления или обходы иерархии, и к которому удобно привязываться.