WPF自定义DatagridColumn绑定问题

我正在尝试为我可以在我的应用程序中重用的数据网格定义一个新的列模板,但是当我尝试使用它时,我得到:

System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement。 BindingExpression:路径= CanLogin; 的DataItem = NULL; target元素是’DataGridBetterCheckBoxColumn’(HashCode = 56040243); target属性是’isChecked’(类型’对象’)

XAML for Column:

       

代码背后:

 using System.Windows; using System.Windows.Controls; namespace BACSFileGenerator.UserControls { public partial class DataGridBetterCheckBoxColumn : DataGridTemplateColumn { public object isChecked { get { return (object)GetValue(isCheckedProperty); } set { SetValue(isCheckedProperty, value); } } public static readonly DependencyProperty isCheckedProperty = DependencyProperty.Register("isChecked", typeof(object), typeof(DataGridBetterCheckBoxColumn), new PropertyMetadata(null)); public DataGridBetterCheckBoxColumn() { InitializeComponent(); } } } 

然后我试着像这样使用它:

          

任何人都可以向我解释这样做的正确方法吗?

让我们说

 public class ViewModel { public bool CanBeUsed {get;set;} public List Employees{get;set;} } 

很少有人可能会让你困惑:

  1. 将只为属性实例化一个DataGridBetterCheckBoxColumn 。 多条记录并不意味着属性的多列实例。 而是为每个DataGridColumn创建多个DataGridColumn

    DataGridColumn不是FrameworkElementVisual因此它不会出现在VisualTree ,因为它不是FrameworkElement所以它没有DataContext属性。 没有DataContext你的Binding将如何工作? 问你自己。 由于此Column无法设置其DataContext ,因此它必须具有ElementNameSourceRelativeSource才能使其Binding工作。

    现在,我们知道DataGridColumn只有一个实例,所以它的Binding自然应该(使用)使用DataGridColumnDataContext (集合属性将是其中的一部分)。

    现在,看看你的Binding ,它的Source / RelativeSource哪里? 没有。 现在, RelativeSource会在这里有意义吗? 由于DataGridColumn没有出现在VisualTree ,因此RelativeSource不适用于此处。 我们留下了Source属性。 我们现在应该为Source设置什么? 输入DataContext Inheritance

    DataContextinheritance

    DataContextinheritance仅适用于通过VisualTree连接的FrameworkElement 。 因此,我们需要一种机制,我们可以使用这种机制将DataContext转移到DataGridColumn 。 输入Binding Proxy

     public class BindingProxy : Freezable { #region Overrides of Freezable protected override Freezable CreateInstanceCore() { return new BindingProxy(); } #endregion public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc... public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); } 

    如果我们将此BindingProxy的实例声明为Resource ,我们可以获取Source

              

    现在,您将看到您讨厌的Binding Error消失了。

  2. 要使CheckBox绑定正常工作,您需要处理其Loaded事件。

           

    代码:

      void CheckBox_Loaded(object sender, RoutedEventArgs e) { Binding b = new Binding(); b.Path = new PropertyPath("isChecked"); b.Mode = BindingMode.TwoWay; b.Source = this; CheckBox cb = sender as CheckBox; BindingOperations.SetBinding(cb , CheckBox.IsCheckedProperty, b); } 

    但现在,我们在这里有一个逻辑问题。 我们所有的CheckBox现在都绑定到DataContext属性CanBeUsed ,它将保持不变。 您可能认为CanBeUsed应该是Employee的属性,它是ItemsSource而不是DataGrid DataContext 。 因此,当您选中/取消选中任何CheckBox ,所有CheckBox都会响应。

但是,我们希望将我们的isChecked属性绑定到Employee记录的某些属性,这将保留每个DataGridRow差异。 所以,我们现在需要更改isChecked的定义,之后整个代码如下所示:

 public partial class DataGridBetterCheckBoxColumn : DataGridTemplateColumn { public BindingBase isChecked { get; set; } public DataGridBetterCheckBoxColumn() { InitializeComponent(); } void CheckBox_Loaded(object sender, RoutedEventArgs e) { CheckBox cb = sender as CheckBox; BindingOperations.SetBinding(cb , CheckBox.IsCheckedProperty, isChecked); } } 

用法:

  

如果我错过任何一点,请告诉我。