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;
}
}
}
我在选择模式下使用 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;
}
}
}