Управление несколькими выборами с помощью MVVM
В моем путешествии по изучению 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?
Ответы
Ответ 1
Добавьте свойство 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); }
}
Ответ 2
Я могу заверить вас: SelectedItems
действительно может быть связан как XAML CommandParameter
Существует простое решение этой общей проблемы; чтобы он работал, вы должны следовать ВСЕ следующим правилам:
-
Следуя рекомендациям Ed Ball, в вашей привязке к команде XAML, укажите атрибут CommandParameter
ПЕРЕД атрибут Command
, Это очень трудоемкая ошибка.
![enter image description here]()
-
Убедитесь, что у ваших методов ICommand
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
SelectedItems
в свои методы ICommand
или ListView
/ListBox
. Отлично, не так ли?
Надеюсь, это мешает кому-то потратить огромное количество времени, которое я сделал, чтобы выяснить, как получить SelectedItems
как параметр CanExecute
.
Ответ 3
Можно попытаться создать прикрепленное свойство.
Это позволит сохранить одно из добавления свойства IsSelected
для каждого связанного списка. Я сделал это для ListBox
, но его можно изменить для использования в виде списка.
<ListBox SelectionMode="Multiple"
local:ListBoxMultipleSelection.SelectedItems="{Binding SelectedItems}" >
Дополнительная информация: WPF - привязка ListBox SelectedItems - привязанный свойство VS Style.
Ответ 4
Если вы используете MVVM-LIGHT, вы можете использовать этот шаблон:
http://blog.galasoft.ch/archive/2010/05/19/handling-datagrid.selecteditems-in-an-mvvm-friendly-manner.aspx
Не особенно элегантно, но выглядит как минимум