WPF Select 来自具有双向绑定的 ViewModel 的 DataGrid 中的多个项目

WPF Select multiple items in DataGrid from ViewModel with twoway binding

我正在尝试创建双向绑定到 WPF DataGrid 中的 selected 项。我希望能够 select 来自 ViewModel 和实际 UserControl 的多个项目。我知道我不能直接设置 selected 项目,因为这个 属性 是只读的。

我正在考虑绑定到 DependencyProperty 并在后面的代码中订阅 DataGridSelectionChanged 事件。

<UserControl.Resources>
    <Style TargetType="local:ListView">
        <Setter Property="SelectedItems" Value="{Binding SelectedItemsVM, Mode=TwoWay}"/>
    </Style>
</UserControl.Resources>

<DataGrid Name="ObjectListDataGrid" SelectionChanged="OnSelectionChanged">

在后面的代码中,我创建了 DependencyProperty。设置后,我订阅了 CollectionChanged 事件。

public ObservableCollection<object> SelectedItems
{
    get { return (ObservableCollection<object>)GetValue(SelectedItemsProperty); }
    set { SetValue(SelectedItemsProperty, value); }
}

public static readonly DependencyProperty SelectedItemsProperty =
    DependencyProperty.Register("SelectedItems", typeof(ObservableCollection<object>), typeof(ListView), new PropertyMetadata(default(ObservableCollection<object>), OnSelectedItemsChanged));

private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var collection = e.NewValue as ObservableCollection<object>;
    if (collection != null)
    {
        collection.CollectionChanged -= OnSelectedItemsCollectionChanged;
        collection.CollectionChanged += OnSelectedItemsCollectionChanged;
    }
}

我使用 EventHandlerSelectionChanged 事件 DataGrid 到 add/remove 集合中的项目。

private void OnSelectionChanged(object sender, SelectionChangedEventArgs args)
{
    SelectedItems.Remove(args.RemovedItems);
    SelectedItems.Add(args.AddedItems);
}

现在我想 select 集合更改时 OnSelectedItemsCollectionChanged 方法中需要的行。

private static void OnSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{   
    foreach (DataGridRow row in ObjectListDataGrid.Rows())
    {
        if(ObjectListDataGrid.SelectedItems.Contains(row.Item))
            row.IsSelected = true;
        else
            row.IsSelected = false;
    }
}

问题: 由于 OnSelectedItemsCollectionChanged 方法是静态的,我无法访问 ObjectListDataGrid。有什么办法可以克服这个问题,或者以不同的方式来解决这个问题?

为了完整起见,DataGrid.Rows() 方法是获取行列表的扩展方法:

public static IEnumerable<DataGridRow> Rows(this DataGrid grid)
{
    var itemsSource = grid.ItemsSource as IEnumerable;
    if (null == itemsSource) yield return null;
    foreach (var item in itemsSource)
    {
        var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
        if (null != row) yield return row;
    }
}

您的 OnSelectedItemsCollectionChanged 方法不能是静态的。

OnSelectedItemsChanged 方法的 DependencyObject 参数转换为您的 ListView class。还要确保将处理程序与 SelectedItems 属性.

的旧值分离
private static void OnSelectedItemsChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var listView = (ListView)d;
    var oldCollection = (INotifyCollectionChanged)e.OldValue;
    var newCollection = (INotifyCollectionChanged)e.NewValue;

    if (oldCollection != null)
    {
        oldCollection.CollectionChanged -= listView.OnSelectedItemsCollectionChanged;
    }

    if (newCollection != null)
    {
        newCollection.CollectionChanged += listView.OnSelectedItemsCollectionChanged;
    }
}

private void OnSelectedItemsCollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    foreach (var row in ObjectListDataGrid.Rows())
    {
        row.IsSelected = ObjectListDataGrid.SelectedItems.Contains(row.Item);
    }
}