多选项目时如何从Listview获取最后一个项目

时间:2018-12-03 11:43:56

标签: c# wpf mvvm multi-select selecteditem

我对multiselect和SelectedItem属性有一点问题。我的应用程序以以下方式工作:当我在Listview中单击记录时,该记录中的数据显示在文本框中。现在这是我的问题。我想要实现类似的功能:当我一个接一个地单击记录时,我想显示最后选择的项目的数据。不幸的是,SelectedItem仅适用于第一个元素。你可以帮帮我吗?我附上了必要的代码部分:

enter image description here

MainWindow.xaml

.route(r -> r.header("Host", "form").uri("http://form:8080"))
                .route(r -> r.path("/form/**")
                        .filters(f -> f.stripPrefix(1))
                        .uri("http://form:8080"))

Employee.cs

<ListView Name="EmployeeListView" HorizontalAlignment="Left" Height="160" Margin="0,153,0,0" VerticalAlignment="Top" Width="755" Grid.Row="1" ItemsSource="{Binding FilteredCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding SelectedIndex}" IsSynchronizedWithCurrentItem="True">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="EmployeeName" Width="150" DisplayMemberBinding="{Binding EmployeeName}" />
                    <GridViewColumn Header="EmployeeID" Width="150" DisplayMemberBinding="{Binding EmployeeID}" />
                    <GridViewColumn Header="EmployeeSalary" Width="150" DisplayMemberBinding="{Binding EmployeeSalary}" />
                    <GridViewColumn Header="EmployeeDesigner" Width="150" DisplayMemberBinding="{Binding EmployeeDesigner}" />
                    <GridViewColumn Header="EmployeeEmailID" Width="150" DisplayMemberBinding="{Binding EmployeeEmailID}" />
                </GridView>
            </ListView.View>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>

2 个答案:

答案 0 :(得分:0)

我玩了一会儿,想出了这个解决方案。
我的目标是尽可能利用Binding
如果您发现任何错误,请通知我。

我创建了一个附加行为和相应的附加属性

public static class LastSelectedItemBehavior
{
    public static readonly DependencyProperty ExposeLastSelectedItemProperty =
        DependencyProperty.RegisterAttached("ExposeLastSelectedItem", typeof(bool), typeof(LastSelectedItemBehavior),
            new PropertyMetadata(false, ExposeLastSelectedItemChanged));
    public static bool GetExposeLastSelectedItem(ListBox element)
    {
        return (bool)element.GetValue(ExposeLastSelectedItemProperty);
    }
    public static void SetExposeLastSelectedItem(ListBox element, bool value)
    {
        element.SetValue(ExposeLastSelectedItemProperty, value);
    }
    private static void ExposeLastSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is ListBox listBox && e.NewValue is bool boolValue)
        {
            if (boolValue)
            {
                listBox.SelectionChanged += ListBox_SelectedItemsChanged;
            }
            else
            {
                listBox.SelectionChanged -= ListBox_SelectedItemsChanged;
            }
        }
    }
    private static void ListBox_SelectedItemsChanged(object sender, SelectionChangedEventArgs e)
    {
        var listBox = (ListBox) sender;
        listBox.SetValue(LastSelectedItemPropertyKey, listBox.SelectedItems.Count > 0 ? listBox.SelectedItems[listBox.SelectedItems.Count - 1] : default(object));
    }

    private static readonly DependencyPropertyKey LastSelectedItemPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly(
            "LastSelectedItem", 
            typeof(object), 
            typeof(LastSelectedItemBehavior),
            new PropertyMetadata(default(object)));
    public static readonly DependencyProperty LastSelectedItemProperty = LastSelectedItemPropertyKey.DependencyProperty;

    public static object GetLastSelectedItem(ListBox element)
    {
        return element.GetValue(LastSelectedItemProperty);
    }
}

您必须在ListView上设置ExposeLastSelectedItem

<ListView x:Name="listView" local:LastSelectedItemBehavior.ExposeLastSelectedItem="True" />

然后您可以像这样绑定

<ContentControl Content="{Binding ElementName=listView, Path=(local:LastSelectedItemBehavior.LastSelectedItem)}" />

编辑:

使用Dmitry Tashkinov中的方法对MVVM友好的解决方案

<ListView x:Name="listView" local:LastSelectedItemBehavior.ExposeLastSelectedItem="True">
    <local:DataPiping.DataPipes>
        <local:DataPipeCollection>
            <local:DataPipe 
                Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=(local:LastSelectedItemBehavior.LastSelectedItem)}"
                Target="{Binding Path=LastSelectedItem, Mode=OneWayToSource}"/>
        </local:DataPipeCollection>
    </local:DataPiping.DataPipes>
</ListView>

答案 1 :(得分:-1)

我已经解决了自己的问题。我附加了部分添加的代码。 首先,您必须从此article开始执行步骤。必须处理交互触发器。解决方案:选择项目时,将其索引添加到列表中。 SelectedItem属性设置在我选择的所选项目上。然后,将这些索引在列表中的这些雇员的IsSelected属性设置为true。我使用HashSet来避免重复值:当我选择列表中的第二个项目时,第一个选定项目的索引又一次添加到列表中。随时发表评论:)

enter image description here

XAML文件(添加到ListView控件):

            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding SelectionChanged}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>

Employee.cs文件

        public HashSet<int> IndexesOfSelectedEmployees
        {
            get
            {
                return indexesOfSelectedEmployees;
            }
            set
            {
                indexesOfSelectedEmployees = value;
                OnPropertyChanged("IndexesOfSelectedEmployees");
            }
        }

EmployeeViewModel.cs文件:

          public void OnSelectionChanged(object parameter)
          {

            if(SelectedEmployee == null)
            {
                IndexesOfSelectedEmployees.Clear();
            }
            if(SelectedEmployee != null)
            {
                foreach (Employee item in Employees)
                {
                    if (item.IsSelected == true)
                    {
                        IndexesOfSelectedEmployees.Add(SelectedIndex.GetValueOrDefault());
                    }
                }
                foreach (int itemIndexesOfSelectedEmployees in IndexesOfSelectedEmployees)
                {
                    foreach (Employee itemEmployees in Employees)
                    {
                        if (itemIndexesOfSelectedEmployees == Employees.IndexOf(itemEmployees))
                        {
                            itemEmployees.IsSelected = true;
                        }
                    }
                }
          }