Просмотр списка с флажками

#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:

  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 было бы:

  1. Поскольку привязки являются двусторонними, вам не нужно ничего делать, чтобы обновить ваш объект из пользовательского интерфейса. Но если вы хотите, чтобы ваш пользовательский интерфейс обновлялся при изменениях в модели, ваши классы модели должны реализовать INotifyPropertyChanged
  2. Я предполагаю, что это было бы сделано в IsReceived установщике. Добавьте два поля в свой класс модели.

 public string ValidationError
{ get; set; }

public bool HasValidationError
{ get; set; }
  

Затем создайте всплывающее окно с ошибкой, которая по умолчанию скрыта. Реализуйте INotifyPropertyChanged в своем классе и привяжите видимость всплывающего окна к HasValidationError , а сообщение во внутреннем TextBlock — к ValidationError .

Комментарии:

1. Есть ли что-то конкретное для этого случая, что это все равно не будет применяться? Та же логика должна быть жизнеспособной. Если есть что-то, что делает это очень сложным, вам следует подумать о создании ViewModel, который выполнял бы любые необходимые вычисления или обходы иерархии, и к которому удобно привязываться.