This question is not "how to do it", but I want to understand "why this is happening."

There is a window, in it a DataGrid, in a DataGrid there is a DataGridTemplateColumn, in which DataTemplate with UserControl

Inside the target UserControl, both the DataContext of the item and the parent DataContext of the window are required for binding to the commands.

We try the option with an explicit transfer, so as not to bathe with AncestorLevel

To remove UserControl's dependency on the nesting level, we make it a DependencyProperty

public static readonly DependencyProperty MainContextProperty = DependencyProperty.Register( "MainContext", typeof(object), typeof(CellView), new PropertyMetadata(default(object))); public object MainContext { get { return (object) GetValue(MainContextProperty); } set { SetValue(MainContextProperty, value); } } 

Passing the parent context .:

  <CellView MainContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, Mode=OneTime}}" /> 

Context inside UserControl, we are going to command:

 Command="{Binding MainContext.MyCommand, RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor, AncestorLevel=1}, Mode=OneTime}" 

And it does not work. It works if you put OneWay. And if you make AncestorLevel = 2, then it will get to the parent context and will work with OneTime

What happens to the DataContext during this transfer? And why does Oneway work?

  • And what is the actual MainContext in UserControl actually? - VladD
  • @VladD Hanged on UC Loaded and got MainContext in it. And in the studio I watched and did GetType. It is equal to the view model, which is the main DataContext, that is, what is expected. - vitidev
  • @VladD Maybe this is - the control is initialized in its constructor and at that moment runs to the MainContext property, but is it null at that moment, and only then it is assigned? I do not know exactly when the properties specified in xaml - vitidev are set
  • Yeah, about that now I write the answer just now. - VladD
  • Hmm, why does AncestorLevel = 2 work at all? Do you have two nested UserControls? - VladD

1 answer 1

I think the reason is when exactly one-time binding occurs. It occurs at the time of InitializeComponent , when XAML is read and interpreted.

At this point, apparently, the MainContext binding MainContext not yet been executed, since the external UserControl not yet been inserted into the visual tree. So Binding bound to the value null .

When AncestorLevel=2 is specified, Binding sees that the search rests on the root (while the external UserControl constructed, it is the UserControl itself). The binding resolution is postponed (this is a multi-phase process, yes), and now when the element is still inserted into the tree, the desired Ancestor is located, and at that moment it has the correct MainContext value.

In the case of OneWay instead of OneTime it is still simpler: at first, the MainContext not set, but when all assignments are “settled”, it will change, and this change will be “picked up” by the binding, because it is no longer one-time now.

  • From this conclusion - should I either use the DataContext property with inheritance, or create the same MainContext property for the parent, and for the control, set the inherit flag of this property and then it will be set? Or it is not necessary at all if the property to do this? I understand that the attached property is inherited implicitly by the automaton to all the nested, but the usual properties are not discussed. - vitidev
  • @vitidev: The inherit flag near the attached property itself. I would create it with the inherit flag, and bound it at the topmost <Window MainContext="{Binding}" ... /> , and inside I referenced: Command="{Binding MainContext.MyCommand, RelativeSource={RelativeSource Self}, Mode=OneWay}" . - VladD
  • @vitidev: If, of course, the command is not in the context menu, there you need to "stitch" the visual tree. - VladD
  • for the context menu, I make DataContext as a resource in such a simple way thomaslevesque.com/2011/03/21/… . Hemming is more cumbersome. - vitidev
  • @vitidev: Well, yes, but it will not allow breaking the code into several files. - VladD