DataGridTemplateColumn get value of cell

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-04 22:08:19

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!