Xceed DataGrid 设置为 row:MultiSelect - 如何将所选行绑定到其 MVVM 行数据

Xceed DataGrid set to row:MultiSelect - How to bind selected row to its MVVM row data

我在选择模式下使用 Xceed DataGridControl 设置为 "Extended"(多选)。

我正在使用 MVVM。每行都绑定到我的 class MyRowObject 的一个实例。 MyRowObject 有一个布尔值 属性 "IsSelected"。我想将 DataGridControl 行 "IsSelected" 属性(如果有的话,我找不到 read/write)绑定到我的 MyRowObject.IsSelected。

有谁知道是否可以使用 Xceed DataGridControl 来实现以及如何实现?如果没有直接绑定可能,有人为此编写了行为吗?

实际上,直接这样做是不可能的。到目前为止 (2016-04-25) 的任何版本都是如此。

但 Xceed 非常友好地为我提供了实现相同行为的代码(见下文)。我稍微修改了他们的代码,以便将其双向放置并防止出现异常,但除此之外的行为正是我想要的。请注意,它被硬编码为 属性 "IsSelected".

不要使用:DataGridControl,而是使用:DataGridControlCustom。

using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using Xceed.Wpf.DataGrid;

namespace XceedUtil
{
    public class DataGridControlCustom : DataGridControl
    {
        public DataGridControlCustom()
        {
            SelectionChanged += OnSelectionChanged;
        }

        private void OnSelectionChanged(object sender, DataGridSelectionChangedEventArgs e)
        {
            foreach (SelectionInfo selectionInfo in e.SelectionInfos)
            {
                foreach (var item in selectionInfo.AddedItems)
                {
                    PropertyInfo pi = item.GetType().GetProperty("IsSelected", BindingFlags.Public | BindingFlags.Instance);
                    if (pi != null && pi.CanWrite)
                    {
                        pi.SetValue(item, true);
                    }
                }
                foreach (var item in selectionInfo.RemovedItems)
                {
                    PropertyInfo pi = item.GetType().GetProperty("IsSelected", BindingFlags.Public | BindingFlags.Instance);
                    if (pi != null && pi.CanWrite)
                    {
                        pi.SetValue(item, false);
                    }
                }
            }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new CustomDataRow();
        }
    }

    public class CustomDataRow : DataRow, IWeakEventListener
    {
        protected override void PrepareContainer(DataGridContext dataGridContext, object item)
        {
            base.PrepareContainer(dataGridContext, item);

            PropertyInfo pi = item.GetType().GetProperty("IsSelected", BindingFlags.Public | BindingFlags.Instance);
            if (pi != null && pi.CanWrite)
            {
                if ((bool)pi.GetValue(item) == true)
                {
                    dataGridContext.SelectedItems.Add(item);
                }
            }

            PropertyChangedEventManager.AddListener(item as INotifyPropertyChanged, this, "IsSelected");
        }

        private void UpdateSelectedItems(object item)
        {
            var selectedItems = DataGridControl.GetDataGridContext(this).SelectedItems;
            try
            {
                PropertyInfo pi = item.GetType().GetProperty("IsSelected", BindingFlags.Public | BindingFlags.Instance);
                if (pi != null && pi.CanWrite)
                {
                    if ((bool) pi.GetValue(item) == true)
                    {
                        selectedItems.Add(item);
                    }
                    else
                    {
                        selectedItems.Remove(item);
                    }
                }
            }
            catch (InvalidOperationException ex)
            {

            }
        }

        protected override void ClearContainer()
        {
            var item = this.DataContext;
            PropertyChangedEventManager.RemoveListener(item as INotifyPropertyChanged, this, "IsSelected");

            var selectedItems = DataGridControl.GetDataGridContext(this).SelectedItems.Remove(item);

            base.ClearContainer();
        }

        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            if (managerType == typeof(PropertyChangedEventManager))
            {
                this.UpdateSelectedItems(sender);
            }

            return true;
        }
    }
}