DataGridTemplateColumn 获取单元格的值

发布于 2024-08-15 16:39:39 字数 302 浏览 11 评论 0原文

我正在使用 WPF 工具包中的 WPF DataGrid

我向 DataGrid 添加了一个模板化列,其中每个单元格中都有一个 CheckBox。现在如何访问这些单元格中的值?

DataGrid 中的其他列来自 DataSet。我可以访问这些,但无法获取添加到 DataGridDataGridTemplateColumn 的值。

有人有什么想法吗?

I'm using the WPF DataGrid from the WPF Toolkit.

I added a templated column to my DataGrid, which has a CheckBox in each cell. Now how do I access the values within these cells?

My other columns in the DataGrid come from a DataSet. I can access these, but I cannot get to the values of the DataGridTemplateColumn I added to the DataGrid.

Anyone have any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

两仪 2024-08-22 16:39:39

现在你要从视觉树中取出东西了。这是一项艰苦的工作,您找不到绑定,因为它被埋在单元格模板中。我所做的就是为此类内容添加我自己的列,该列派生自 DataGridBoundColumn,这意味着它具有像所有其他列一样的绑定:(我不久前写过它,它可能需要一些查看)这让我只使用直装订。我不必设置单元格模板,我可以使用我更喜欢的 DataTemplate。

   public class DataGridReadOnlyObjectDisplayColumn : DataGridBoundColumn {

      public DataGridReadOnlyObjectDisplayColumn() {
         //set as read only,
         this.IsReadOnly = true;
      }


      /// <summary>
      /// Gets and Sets the Cell Template for this column
      /// </summary>
      public DataTemplate CellTemplate {
         get { return (DataTemplate)GetValue(CellTemplateProperty); }
         set { SetValue(CellTemplateProperty, value); }
      }

      // Using a DependencyProperty as the backing store for CellTemplate.  This enables animation, styling, binding, etc...
      public static readonly DependencyProperty CellTemplateProperty =
          DependencyProperty.Register("CellTemplate", typeof(DataTemplate), typeof(DataGridReadOnlyObjectDisplayColumn), new UIPropertyMetadata(null));



      protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem) {
         //create the simple field text block
         ContentControl contentControl = new ContentControl();

         contentControl.Focusable = false;

         //if we have a cell template use it
         if (this.CellTemplate != null) {
            contentControl.SetValue(ContentControl.ContentTemplateProperty, this.CellTemplate);
         }

         //set the binding
         ApplyBinding(contentControl, ContentPresenter.ContentProperty);

         //return the text block
         return contentControl;
      }

      /// <summary>
      ///     Assigns the Binding to the desired property on the target object.
      /// </summary>
      internal void ApplyBinding(DependencyObject target, DependencyProperty property) {
         BindingBase binding = Binding;

         if (binding != null) {
            BindingOperations.SetBinding(target, property, binding);
         }
         else {
            BindingOperations.ClearBinding(target, property);
         }
      }

      protected override System.Windows.FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem) {
         //item never goes into edit mode it is a read only column
         return GenerateElement(cell, dataItem);
      }
   }

现在,如果您可以到达该列,您就可以到达该列上的绑定。如果您可以到达该单元格,那么您就可以找到数据项(行数据)。然后我要做的就是按照绑定来获取单元格值。它确实效率低下,而且是一种 hack。但它有效。为了遵循绑定,我使用这个。

 private Object GetCellValue(Binding columnBinding, object dataSource) {

     Object valueField = null;

     if (columnBinding != null) {
        BindingEvaluator bindingEvaluator = new BindingEvaluator();

        //copy the binding
        Binding binding = new Binding();
        binding.Path = columnBinding.Path;
        binding.Source = dataSource;

        //apply the binding
        BindingOperations.SetBinding(bindingEvaluator, BindingEvaluator.BindingValueProperty, binding);

        //get the current cell item
        valueField = bindingEvaluator.BindingValue as IValueField;
     }

     return valueField;
  }

最后一部分是一个名为 BindingEvaluator 的辅助类,它有一个 dp,我用它来跟踪绑定

   public class BindingEvaluator : DependencyObject {

      /// <summary>
      /// Gets and Sets the binding value
      /// </summary>
      public Object BindingValue {
         get { return (Object)GetValue(BindingValueProperty); }
         set { SetValue(BindingValueProperty, value); }
      }

      // Using a DependencyProperty as the backing store for BindingValue.  This enables animation, styling, binding, etc...
      public static readonly DependencyProperty BindingValueProperty =
          DependencyProperty.Register("BindingValue", typeof(Object), typeof(BindingEvaluator), new UIPropertyMetadata(null));
   }

,我这样称呼它:

 var valueField = this.GetCellValue(column.Binding as Binding, datagrid.CurrentCell.Item);

your into pulling stuff out of the visual tree now. and thats hard work, you cant find the binding because that is buried in the cell template. what i did was add my own column for this kind of stuff, the column derives from DataGridBoundColumn, which means it has a binding like all the others: ( i wrote it a while ago, it could probably do with some looking at ) This lets me just use a straight binding. i dont have to set a cell template, i can just use a DataTemplate which i like better.

   public class DataGridReadOnlyObjectDisplayColumn : DataGridBoundColumn {

      public DataGridReadOnlyObjectDisplayColumn() {
         //set as read only,
         this.IsReadOnly = true;
      }


      /// <summary>
      /// Gets and Sets the Cell Template for this column
      /// </summary>
      public DataTemplate CellTemplate {
         get { return (DataTemplate)GetValue(CellTemplateProperty); }
         set { SetValue(CellTemplateProperty, value); }
      }

      // Using a DependencyProperty as the backing store for CellTemplate.  This enables animation, styling, binding, etc...
      public static readonly DependencyProperty CellTemplateProperty =
          DependencyProperty.Register("CellTemplate", typeof(DataTemplate), typeof(DataGridReadOnlyObjectDisplayColumn), new UIPropertyMetadata(null));



      protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem) {
         //create the simple field text block
         ContentControl contentControl = new ContentControl();

         contentControl.Focusable = false;

         //if we have a cell template use it
         if (this.CellTemplate != null) {
            contentControl.SetValue(ContentControl.ContentTemplateProperty, this.CellTemplate);
         }

         //set the binding
         ApplyBinding(contentControl, ContentPresenter.ContentProperty);

         //return the text block
         return contentControl;
      }

      /// <summary>
      ///     Assigns the Binding to the desired property on the target object.
      /// </summary>
      internal void ApplyBinding(DependencyObject target, DependencyProperty property) {
         BindingBase binding = Binding;

         if (binding != null) {
            BindingOperations.SetBinding(target, property, binding);
         }
         else {
            BindingOperations.ClearBinding(target, property);
         }
      }

      protected override System.Windows.FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem) {
         //item never goes into edit mode it is a read only column
         return GenerateElement(cell, dataItem);
      }
   }

now if you can get to the column you can get to the binding on the column. if you can get to the cell then you can find the data item (the row data). then what i do is follow the binding to get the cell value. it is really inefficient, and it is a hack. but it works. to follow the binding i use this.

 private Object GetCellValue(Binding columnBinding, object dataSource) {

     Object valueField = null;

     if (columnBinding != null) {
        BindingEvaluator bindingEvaluator = new BindingEvaluator();

        //copy the binding
        Binding binding = new Binding();
        binding.Path = columnBinding.Path;
        binding.Source = dataSource;

        //apply the binding
        BindingOperations.SetBinding(bindingEvaluator, BindingEvaluator.BindingValueProperty, binding);

        //get the current cell item
        valueField = bindingEvaluator.BindingValue as IValueField;
     }

     return valueField;
  }

and the last piece is a helper class called BindingEvaluator which has one dp, that i use to follow the binding

   public class BindingEvaluator : DependencyObject {

      /// <summary>
      /// Gets and Sets the binding value
      /// </summary>
      public Object BindingValue {
         get { return (Object)GetValue(BindingValueProperty); }
         set { SetValue(BindingValueProperty, value); }
      }

      // Using a DependencyProperty as the backing store for BindingValue.  This enables animation, styling, binding, etc...
      public static readonly DependencyProperty BindingValueProperty =
          DependencyProperty.Register("BindingValue", typeof(Object), typeof(BindingEvaluator), new UIPropertyMetadata(null));
   }

and i call it like so:

 var valueField = this.GetCellValue(column.Binding as Binding, datagrid.CurrentCell.Item);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文