【问题标题】:prism 5.0 InvokeCommandAction SelectionMode="Multiple"棱镜 5.0 InvokeCommandAction SelectionMode="Multiple"
【发布时间】:2017-03-01 12:26:23
【问题描述】:

我想通过 InvokeCommandAction prism 5.0 检测列表框中的所有选定项。

XAML

<Window x:Class="Selection.Prism5._0.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:Selection.Prism5"
    xmlns:prism="http://www.codeplex.com/prism"
    mc:Ignorable="d"
    Title="MainWindow"
    Height="350"
    Width="525">
<FrameworkElement.DataContext>
    <local:MainViewModel />
</FrameworkElement.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="5" />
        <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>
    <ListBox SelectedItem="{Binding SelectedItem}"
             ItemsSource="{Binding Items}"
             SelectionMode="Multiple">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <prism:InvokeCommandAction Command="{Binding SelectItemsCommand}"
                                           TriggerParameterPath="AddedItems" />
            </i:EventTrigger>
        </i:Interaction.Triggers>

        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>

查看模型

  public class MainViewModel : BindableBase
{
    public MainViewModel()
    {
        this.Items = new List<Model>
        {
           new Model {Id=1,Name="Name 1" },
           new Model {Id=2,Name="Name 2" },
           new Model {Id=3,Name="Name 3" },
           new Model {Id=4,Name="Name 4" },
           new Model {Id=5,Name="Name 5" },
           new Model {Id=6,Name="Name 6" }
        };
        SelectItemsCommand = new DelegateCommand<object[]>((items) =>
        {
            if (items != null && items.Count() > 0)
            {
                SelectedItems = items.Select(i => (Model)i);
            }
        });

    }



    public ICommand SelectItemsCommand { get; private set; }

    private IEnumerable<Model> _items;
    public IEnumerable<Model> Items
    {
        get { return _items; }
        set
        {
            _items = value; base.OnPropertyChanged("Items");
        }
    }


    private IEnumerable<Model> _selectedItems;
    public IEnumerable<Model> SelectedItems
    {
        get { return _selectedItems; }
        set
        {
            _selectedItems = value; base.OnPropertyChanged("SelectedItems");
        }
    }
    private Model _selectedItem;
    public Model SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value; base.OnPropertyChanged("SelectedItem");
        }
    }
}

它应该工作,但它没有。当我在 GUI 中选择多个项目时:

查看模型代码只识别一项:

我在 Brian Lagunas 的 "What's New in Prism 5.0" 中看到了这个例子,据我所知,这个技术也可以用于多选。 我在这里做错了什么?

【问题讨论】:

  • 您一次选择一个项目,并为每个项目调用该命令。这是预期的行为。

标签: wpf mvvm prism prism-5


【解决方案1】:

SelectionChangedEventArgs.AddedItems 为您提供特定操作的选择列表。如果 ListBox SelectionMode"Multiple""Single" 您不能一次单击选择多个项目。如果 ListBox SelectionMode"Extended" 您可以在 shift 键的帮助下选择多个项目。

SelectionChangedEventArgs.AddedItems 不会为特定操作提供列表框的所有选定项。

根据您的需要,

在视图中,

TriggerParameterPath="AddedItems" 更改为TriggerParameterPath="Source.SelectedItems"

在视图模型中

DelegateCommand&lt;object[]&gt; 更改为DelegateCommand&lt;System.Collections.ICollection&gt;

参考: http://frststart.blogspot.com/2016/10/selectionchangedselecteditemstutorial.html

【讨论】:

    【解决方案2】:

    您一次选择一个项目,每次选择一个项目时都会调用该命令。

    这是预期的行为。

    如果您想跟踪当前选定的项目,您可以将IsSelected 属性添加到Model 类并使用ItemContainerStyle 将此属性绑定到ListBoxItem 容器的IsSelected 属性:

    <ListBox SelectedItem="{Binding SelectedItem}"
                 ItemsSource="{Binding Items}"
                 SelectionMode="Multiple">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <prism:InvokeCommandAction Command="{Binding SelectItemsCommand}"
                                               TriggerParameterPath="AddedItems" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="IsSelected" Value="{Binding IsSelected}" />
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    SelectItemsCommand = new DelegateCommand<System.Collections.IList>((items) =>
    {
        SelectedItems = Items.Where(x => x.IsSelected).ToList();
    });
    

    【讨论】:

    • 感谢您的想法。这可能有效,但是我认为这个解决方案太棘手了:1)。棱镜的使用 2)。甚至触发 3)。命令绑定虽然可以通过一种行为和几行代码来解决它。这是否意味着没有直接的棱镜多选解决方案?
    • 棘手?不,这就是 MVVM 模式的工作原理。如果你认为这个解决方案很“棘手”,你应该学习 MVVM。并且 Prism 只是将 EventArgs 的 AdditionalItems 属性的实际值传递给命令,这将只包含我在回答中解释的新选择的项目。棱镜与此无关。
    • 亲亲。我不喜欢编写冗余代码。我不需要使用所有这些技巧来实现多选,因为它可以通过使用自定义行为和绑定到 SelectedItems 来非常简单地实现。 xaml 和代码后面的代码更简单,代码更少。我以前做过,但我认为棱镜可能会更简单。我错了。
    • 有点解决了 :) 我仍然会使用行为。我只是尝试使用 prism5.0 的功能。根据我上面提到的视频课程,可以通过棱镜实现多选,我不需要为多选编写行为。谢谢。
    • 如前所述,您应该跟踪视图模型中的选定项目,但 InvokeCommandAction 只会将最新选定的项目传递给命令。我想这回答了你原来的问题。如果您有其他问题,您应该提出一个新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2012-01-03
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 2011-02-15
    • 2015-04-19
    相关资源
    最近更新 更多