首页 > 解决方案 > WPF ListView Multi-Select MVVM,后面有最少的代码

问题描述

我试图在 WPF 中实现一种方式,让用户在一个框中选择多个项目,然后通过按钮单击将这些选定的项目添加到另一个框中。

我正在尝试使用最少的代码来遵守 MVVM。我找到的解决方案显示 DataContext 正在通过我试图避免的 View 代码进行操作。

我认为我的问题是我不知道如何从 xaml 切换 IsSelected,但不确定。

在此处输入图像描述

XAML

<ListView
                            ItemsSource="{Binding AvailableStates, Mode=TwoWay}"
                            SelectedItem="{Binding SelectedStates, Mode=TwoWay}"
                            SelectionMode="Multiple"

                            DisplayMemberPath="state"
                            Grid.Row="1" 
                            Margin="5"
                            Grid.Column="1" 
                            Height="125"
                            Name="lvAvailableStates"
                            Grid.RowSpan="6" 
                            ScrollViewer.VerticalScrollBarVisibility="Visible"
                            ScrollViewer.CanContentScroll="True">
                            <ListView.ItemContainerStyle>
                                <Style TargetType="{x:Type ListBoxItem}">
                                    <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                                </Style>
                            </ListView.ItemContainerStyle>
                        </ListView>

<Button
                        Grid.Row="2"
                        Grid.Column="2"
                        Margin="10"
                            Command="{Binding AddSelectedStatesCommand}"
                        Content=">>" />

视图模型

 private ObservableCollection<SelectableItemWrapper<states_approved>> _selectedStates;
    public ObservableCollection<SelectableItemWrapper<states_approved>> SelectedStates
    {
        get { return _selectedStates; }
        set
        {

            _selectedStates = value;
            OnPropertyChanged();
        }
    }

    private void AddSelectedStates(object obj)
    {
        var selected = SelectedStates.Where(s => s.IsSelected)
            .Select(s => s.Item)
            .ToList();

        StatesApproved = selected;
    }

public CustomCommand AddSelectedStatesCommand
    {
        get
        {
            return new CustomCommand(AddSelectedStates, CanExecute);
        }
    } 

选定项目包装器

public class SelectableItemWrapper<T>
{
    public bool IsSelected { get; set; }
    public T Item { get; set; }
}

标签: c#wpfmvvm

解决方案


ListView具有确定选择哪个项目的内部属性,并且还必须SelectedItems确定多个选定项目。但是,这个复数SelectedItemsofListView是不可绑定的。因此,解决方案是将它们作为CommandParameter.

<ListView x:Name="lvAvailableStates"
          ItemsSource="{Binding AvailableStates, Mode=TwoWay}"
          SelectedItem="{Binding SelectedStates, Mode=TwoWay}" => remove this!
          ...

<Button Command="{Binding AddSelectedStatesCommand}"
        CommandParameter="{Binding SelectedItems, Mode=OneWay, ElementName=lvAvailableStates}" => add this!
        ...

在虚拟机中

private void AddSelectedStates(IEnumerable<SelectableItemWrapper<states_approved>> selectedItems)
{
    StatesApproved = selectedItems
        .Select(s => s.Item) // only retrieve the Item
        .ToList();
}

正如您在这一点上所看到的,您甚至不需要一开始SelectableItemWrapper就设置/取消设置IsSelected属性。你应该去掉包装,生活会更轻松。


推荐阅读