Управление несколькими выборками с помощью MVVM

StackOverflow https://stackoverflow.com/questions/803216

  •  03-07-2019
  •  | 
  •  

Вопрос

На моем пути к изучению MVVM я приобрел некоторое базовое представление о WPF и шаблоне ViewModel.Я использую следующую абстракцию при предоставлении списка, и меня интересует один выбранный элемент.

public ObservableCollection<OrderViewModel> Orders { get; private set; }
public ICollectionView OrdersView
{
    get
    {
        if( _ordersView == null )
            _ordersView = CollectionViewSource.GetDefaultView( Orders );
        return _ordersView;
    }
}
private ICollectionView _ordersView;

public OrderViewModel CurrentOrder 
{ 
    get { return OrdersView.CurrentItem as OrderViewModel; } 
    set { OrdersView.MoveCurrentTo( value ); } 
}

Затем я могу привязать OrdersView вместе с поддержкой сортировки и фильтрации к списку в WPF:

<ListView ItemsSource="{Binding Path=OrdersView}" 
          IsSynchronizedWithCurrentItem="True">

Это действительно хорошо работает для представлений с одним выделением.Но я бы хотел также поддерживать множественный выбор в представлении и привязать модель к списку выбранных элементов.

Как бы я привязал ListView.SelectedItems к свойству backer в ViewModel?

Это было полезно?

Решение

Добавить IsSelected свойство для вашей дочерней ViewModel (OrderViewModel в вашем случае):

public bool IsSelected { get; set; }

Привяжите выбранное свойство в контейнере к этому (в данном случае для ListBox):

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
    </Style>
</ListBox.ItemContainerStyle>

IsSelected обновляется, чтобы соответствовать соответствующему полю в контейнере.

Вы можете получить выбранные дочерние элементы в модели представления, выполнив следующие действия:

public IEnumerable<OrderViewModel> SelectedOrders
{
    get { return Orders.Where(o => o.IsSelected); }
}

Другие советы

Я могу вас заверить: SelectedItems действительно привязан как XAML CommandParameter

Существует простое решение этой распространенной проблемы;чтобы это сработало, вы должны следовать ВСЕ следующие правила:

  1. Следующие Предложение Эда Болла, в вашей привязке данных команды XAML определите CommandParameter атрибут ДО ТОГО, КАК тот самый Command атрибут. Это очень трудоемкая ошибка.

    enter image description here

  2. Убедитесь, что ваш ICommand's CanExecute и Execute методы имеют параметр типа object.Таким образом, вы можете предотвратить заглушенный приводимые исключения, которые возникают всякий раз, когда привязка данных CommandParameter тип не соответствует вашему Command тип параметра метода:

    private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  
    {
         // Your code goes here
    }
    
    private bool OnDeleteSelectedItemsExecute(object SelectedItems)  
    {
        // Your code goes here
    }
    

Например, вы можете либо отправить ListView/ListBox's SelectedItems собственность для вашего ICommand методы или ListView/ListBox сам по себе.Здорово, не правда ли?

Я надеюсь, что это помешает кому-то потратить огромное количество времени, которое я потратил, чтобы выяснить, как получать SelectedItems в качестве CanExecute параметр.

Можно попробовать создать прикрепленное свойство.

Это избавит вас от необходимости добавлять IsSelected свойство для каждого списка, который вы привязываете.Я сделал это для ListBox, но он может быть изменен для использования a в виде списка.

<ListBox SelectionMode="Multiple"
         local:ListBoxMultipleSelection.SelectedItems="{Binding SelectedItems}" >

Подробная информация: WPF – Список привязки выбранных элементов – Присоединенное свойство В ЗАВИСИМОСТИ от стиля .

Если вы используете MVVM-LIGHT, вы можете использовать этот шаблон:

https://galasoft.ch/posts/2010/05/handling-datagrid-selecteditems-in-an-mvvm-friendly-manner

Не особенно элегантно, но выглядит так, что, по крайней мере, должно быть надежно

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top