Question

My application looks like the following

enter image description here

The black is my MainWindow, the red is a tab control and the yellow is a UserControl.

The UserControl has many Dependency Properties defined and they bind to the DataContext (Which is set in the MainWindow's code behind, using this.DataContext = this).

To bind my UserControl to the same DataContext as my MainWindow, in my UserControl xaml I have the following

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=Window}}"

This works great, and when I interact with my UserControl, due to the two way binding, it updates the Properties of my MainWindow, which in turn updates my TabControl!

The issue is, my UserControl now has some extra functionality and as such, needs to bind to the UserControl's code behind (such as values for the GUI).

This is where I'm stuck. I can't bind from my UserControl to my code behind because I've already created a DataContext.

I know I could use the WinForms approach, and name each control with x:Name="MyControl" like

MyControl.Text = "This value";

or

MyControl.DataContext = this;

Yeuk I think!!

My question is, is this the only way to go, or can I still use binding.

Was it helpful?

Solution

First of all you don't need to manually set DataContext on UserControl. DataContext is an inheritable property so it will inherit DataContext from its parent unless you have explicitly set it.

Get rid of DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=Window}}" from your UserControl.


And now, in case you want to bind to code behind for some controls in your UserControl, you can bind using RelativeSource or can set DataContext on control:

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                                     AncestorType=UserControl}}"

If controls can be clubbed together under one panel, set DataContext on parent panel say Grid and child controls will inherit from it:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                            AncestorType=UserControl}}">
   ..Child Controls here will inherit DataContext
</Grid>

And to answer your question:

MyControl.DataContext = this; <-- Is this possible

Yes, it is possible like i mentioned above.

OTHER TIPS

You can just use another RelativeSource Binding as you have for the MainWindow properties... to access the properties defined in the UserControl, try the following XAML in your UserControl:

<TextBlock Text="{Binding UserControlProperty, RelativeSource={RelativeSource 
    AncestorType={x:Type YourXmlNamespacePrefix:YourUserControl}}}" />

Obviously, you'll need to update YourXmlNamespacePrefix:YourUserControl to a valid XML Namespace and control type to get this to work.


I'm not saying either that you should set the DataContext anywhere, or change any properties. This is a RelativeSource Binding... you do not need to set any DataContext to make it work. I thought you would have known that seeing as you're already using one. Just try the example out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top