Dave
Dave

Reputation: 15016

Databinding a TabItem to a parent Window

I'm trying to clean up the way I use DataContexts with my UserControls, and currently am running into a problem where I need to databind a UserControl inside of a TabItem to the parent Window's DataContext.

Here is a sketch of what my Window looks like:

enter image description here

As you can see, this Window owns a TabControl that contains TabItems that are dynamically added via the "Tabs" ItemSource. Databinding at this point is working because "Tabs" gets populated with Tab 1.

Tab 1 contains a UserControl that needs access to multiple string properties in the DiagnosticsViewModel, but when I run my application, the Output window indicates that all bindings have failed. For example:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=Property1; DataItem=null; target element is 'Tab1UserControl' (Name=''); target property is 'UCName' (type 'String')

The XAML for the UserControl in Tab 1 looks something like this:

<Grid>
    <uc:Tab1UserControl UCName="{Binding Property1, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Grid>

where UCName is a String DependencyProperty.

If I am telling WPF that I want to look up the tree and bind to the DataContext for the nearest Window, and my Window's DataContext is set to DiagnosticsViewModel, why isn't it using it for my UserControl's DataContext? I have not set DataContext = this in my UserControl, as I have done improperly many times in the past, with the expectation that my UserControl will be able to inherit the DataContext from its parent.

I would like to see if Snoop can shed light on my problem, but this GUI is being displayed from a MFC application, and Snoop doesn't seem to be able to attach to my WPF dialog.

Upvotes: 1

Views: 1115

Answers (1)

Astrid
Astrid

Reputation: 1828

If you change the source of a binding using RelativeSource, ElementName or the like, the binding will be directly to the element you specify - not its data context. Which means that in your code the user control will try to bind to a property called Property1 on the Diagnostics class itself.

Try using

<Grid>
    <uc:Tab1UserControl UCName="{Binding Path=DataContext.Property1, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Grid>

in the code for your user control and see if that fixes the problem.

(As an aside, the idea of the user control itself knowing that the window it belongs to will have a datacontext with a given property seems like a code smell to me, especially since the point of user controls is that they're reusable - it'd feel better to have a dependency property on the user control and then bind that to the appropriate property when you use it. This may just be due to me lacking context, though.)

Upvotes: 2

Related Questions