There is a DataGrid , it has a DataGridTextColumn column, the column is set to Binding , I get it in the code:

 for (int j = 0; j < grid.Columns.Count; ++j) { if (grid.Columns[j] is DataGridTextColumn) { DataGridTextColumn dgtc = (DataGridTextColumn)grid.Columns[j]; Binding binding = dgtc.Binding as System.Windows.Data.Binding; //Далее код } } 

Now how can I get a hypothetical value on this Binding , if I have my source? Let me explain, there are values ​​in the Grid lines, cell values ​​are displayed depending on the Binding , how do I know what will be displayed in the cell if the collection item is any other, just to find out, it is not necessary to display the values ​​on the form!

    2 answers 2

    If you just want to know the value, in my opinion, the easiest way to hook the converter.

     <converter:DoNothingConverter x:Key="localDoNothingConverter"></converter:DoNothingConverter> 

    specify in the binding: Converter={StaticResource localDoNothingConverter}}"

      public class DoNothingConverter: IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Debug.WriteLine(value.ToString()); //ну или еще чего здесь сами придумейте return value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } } 
    • Yes, that's with the converter is simple. And I need a wider spectrum - Dmitry Chistik

    It turned out all quite difficult.

    Used articles:

    Get result of a binding in code ,

    Binding doesn’t have a way to copy it

    1. Create a method for cloning Binding , so as not to screw up the main (taken) Binding .

     public static BindingBase CloneBinding(BindingBase bindingBase, object source) { var binding = bindingBase as Binding; if (binding != null) { var result = new Binding { Source = source, AsyncState = binding.AsyncState, BindingGroupName = binding.BindingGroupName, BindsDirectlyToSource = binding.BindsDirectlyToSource, Converter = binding.Converter, ConverterCulture = binding.ConverterCulture, ConverterParameter = binding.ConverterParameter, //ElementName = binding.ElementName, FallbackValue = binding.FallbackValue, IsAsync = binding.IsAsync, Mode = binding.Mode, NotifyOnSourceUpdated = binding.NotifyOnSourceUpdated, NotifyOnTargetUpdated = binding.NotifyOnTargetUpdated, NotifyOnValidationError = binding.NotifyOnValidationError, Path = binding.Path, //RelativeSource = binding.RelativeSource, StringFormat = binding.StringFormat, TargetNullValue = binding.TargetNullValue, UpdateSourceExceptionFilter = binding.UpdateSourceExceptionFilter, UpdateSourceTrigger = binding.UpdateSourceTrigger, ValidatesOnDataErrors = binding.ValidatesOnDataErrors, ValidatesOnExceptions = binding.ValidatesOnExceptions, XPath = binding.XPath, }; foreach (var validationRule in binding.ValidationRules) { result.ValidationRules.Add(validationRule); } return result; } var multiBinding = bindingBase as MultiBinding; if (multiBinding != null) { var result = new MultiBinding { BindingGroupName = multiBinding.BindingGroupName, Converter = multiBinding.Converter, ConverterCulture = multiBinding.ConverterCulture, ConverterParameter = multiBinding.ConverterParameter, FallbackValue = multiBinding.FallbackValue, Mode = multiBinding.Mode, NotifyOnSourceUpdated = multiBinding.NotifyOnSourceUpdated, NotifyOnTargetUpdated = multiBinding.NotifyOnTargetUpdated, NotifyOnValidationError = multiBinding.NotifyOnValidationError, StringFormat = multiBinding.StringFormat, TargetNullValue = multiBinding.TargetNullValue, UpdateSourceExceptionFilter = multiBinding.UpdateSourceExceptionFilter, UpdateSourceTrigger = multiBinding.UpdateSourceTrigger, ValidatesOnDataErrors = multiBinding.ValidatesOnDataErrors, ValidatesOnExceptions = multiBinding.ValidatesOnDataErrors, }; foreach (var validationRule in multiBinding.ValidationRules) { result.ValidationRules.Add(validationRule); } foreach (var childBinding in multiBinding.Bindings) { result.Bindings.Add(CloneBinding(childBinding, source)); } return result; } var priorityBinding = bindingBase as PriorityBinding; if (priorityBinding != null) { var result = new PriorityBinding { BindingGroupName = priorityBinding.BindingGroupName, FallbackValue = priorityBinding.FallbackValue, StringFormat = priorityBinding.StringFormat, TargetNullValue = priorityBinding.TargetNullValue, }; foreach (var childBinding in priorityBinding.Bindings) { result.Bindings.Add(CloneBinding(childBinding, source)); } return result; } throw new NotSupportedException("Failed to clone binding"); } 

    2. Next, create a proxy object that will perform the function of translating the Binding and the resource object into a value by Binding

     class DummyDO : DependencyObject { public object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(DummyDO), new UIPropertyMetadata(null)); } 

    3. And the translation function Object + Binding = value

     public static object EvalBinding(BindingBase b) { DummyDO d = new DummyDO(); BindingOperations.SetBinding(d, DummyDO.ValueProperty, b); return d.Value; } 

    4. The function returns all child elements of the specified type

     public static List<T> GetVisualChilds<T>(DependencyObject parent) where T : DependencyObject { List<T> childs = new List<T>(); if (parent != null) { int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { DependencyObject v = VisualTreeHelper.GetChild(parent, i); if (v is T) childs.Add(v as T); childs.AddRange(GetVisualChilds<T>(v)); } } return childs; } 

    then begins a whistle dance with column types. They have 3 types

    1-DataGridBoundColumn and inherited from it

    2-DataGridComboBoxColumn

    3-DataGridTemplateColumn

    PS: ic - the list of objects by which we calculate values ​​via Binding

     for (int i = 0; i < ic.Count; ++i) for (int j = 0; j < grid.Columns.Count; ++j) { object resultValue = null; if (grid.Columns[j] is DataGridBoundColumn) { DataGridBoundColumn dgbc = (DataGridBoundColumn)grid.Columns[j]; BindingBase columnBinding = dgbc.Binding as BindingBase; BindingBase binding = CloneBinding(columnBinding, ic[i]); resultValue = EvalBinding(binding); } if (grid.Columns[j] is DataGridComboBoxColumn) { DataGridComboBoxColumn dgcbc = (DataGridComboBoxColumn)grid.Columns[j]; BindingBase binding = new Binding(dgcbc.DisplayMemberPath) { Source = ic[i] }; resultValue = EvalBinding(binding); } if (grid.Columns[j] is DataGridTemplateColumn) { DataGridTemplateColumn dgtc = (DataGridTemplateColumn)grid.Columns[j]; DataTemplate dt = dgtc.CellTemplate; ContentPresenter control = new ContentPresenter(); control.Content = ic[i]; control.DataContext = ic[i]; control.ContentTemplate = dt; control.Initialized += delegate (object c, EventArgs ea) { FrameworkElement fwe = c as FrameworkElement; fwe.ApplyTemplate(); }; control.BeginInit(); control.EndInit(); List<FrameworkElement> elems = GetVisualChilds<FrameworkElement>(control); resultValue = string.Join(" ", elems.Select(x => x is TextBlock ? ((TextBlock)x).Text : x is TextBox ? ((TextBox)x).Text : null).Where(x => x is string)); } //В resultValue будет значение равное значению в ячейке DataGrid. } 

    Unfortunately, there are several options:

    1. when in DataGridTemplateColumn used ItemsControl with its ItemTemplate . in this case, we will not get a list of values ​​of ItemsControl .

    2. If ElementName or RelativeSource participate in Binding

    If you have any thoughts on this, please respond.

    • Sorry, but it's hard for me to add anything here. He worked with the converter himself, that's why he advised you, but with this ... no. But is it really necessary? In VS2015, there are visual debugging tools for WPF, with the help of which you can see what you need. There was also some kind of programmulino with its help it was possible to peep the whole visual tree, the properties of controls, etc., its name only forgot it. - Bulson
    • I have a DataGrid, I need to export data from it, say, to html. To do this, I need to get all the text values ​​from the Binding columns, however, if the cell is not visual (below or above the displayed information), the controls cannot be obtained from it. So we have to use the scrap and such a mother from the object (DataContext) of the string and binding to get the values ​​of the displayed information in the cell. - Dmitry Chistik
    • I do not quite understand, you also have a data source for this DataGrid, why it’s impossible to work directly with this source in code? Why do you first need to display it, and then suffer with the displayed information, translate it into a digestible format, so to speak? - Bulson
    • @Bulson yes because there is no data in the cell, if it is not visual at the moment, the data appears when the control is initialized, i.e. at his first appearance. Try it yourself and understand. - Dmitry Chistik
    • "... data appears when the control is initialized, that is, when it first appears," but after all, the control is tied to some collection or dataset and displays the data from there ?! - Bulson