Управление несколькими выборами с MVVM - PullRequest
59 голосов
/ 29 апреля 2009

На пути к изучению 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 ); } 
}

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

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

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

Как бы я связал ListView.SelectedItems со свойством бэкера в ViewModel?

Ответы [ 4 ]

94 голосов
/ 29 апреля 2009

Добавьте свойство 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); }
}
12 голосов
/ 22 сентября 2014

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

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

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

    enter image description here

  2. Убедитесь, что ваши методы 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.

4 голосов
/ 02 мая 2014

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

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

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

Дополнительная информация: WPF - Binding ListBox SelectedItems - Присоединенное свойство VS Стиль .

1 голос
/ 23 июля 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...