This question is a “sequel” to this question (I have applied the answer, but it still won’t work).
I’m trying to create an extended ToolBar control for a modular application, which can load its items from multiple data sources (but that is not the issue I’m trying to solve right now, now I want it to work when used as regular ToolBar found in WPF).
In short: I want the ToolBar’s items to be able to bind to the tb:ToolBar’s parents.
I have following XAML code:
<Window Name="myWindow" DataContext="{Binding ElementName=myWindow}" >
<DockPanel>
<tb:ToolBar Name="toolbar" DockPanel.Dock="Top" DataContext="{Binding ElementName=myWindow}>
<tb:ToolBar.Items>
<tb:ToolBarControl Priority="-3">
<tb:ToolBarControl.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>Maps:</TextBlock>
<ComboBox ItemsSource="{Binding SomeProperty, ElementName=myWindow}">
Some info about the types:
-
tb:ToolBaris anUserControlwith dependency propertyItemsof typeFreezableCollection<ToolBarControl>. -
tb:ToolBarControlis anUserControlwith template pretty much identical to ContentControl’s template.
The problem is that the binding in the ComboBox fails (with the usual “Cannot find source for binding with reference”), because its DataContext is null.
Why?
EDIT: The core of the question is “Why is the DataContext not inherited?”, without it, the bindings can’t work.
EDIT2:
Here is XAML for the tb:ToolBar:
<UserControl ... Name="toolBarControl">
<ToolBarTray>
<ToolBar ItemsSource="{Binding Items, ElementName=toolBarControl}" Name="toolBar" ToolBarTray.IsLocked="True" VerticalAlignment="Top" Height="26">
EDIT 3:
I posted an example of what works and what doesn’t: http://pastebin.com/Tyt1Xtvg
Thanks for your answers.
I personally don’t like the idea of setting
DataContextin controls. I think doing this will somehow break the data context inheritance. Please take a look at this post. I think Simon explained it pretty well.At least, try removing
from
and see how it goes.
UPDATE
Actually, keep all your existing code (ignore my previous suggestion for a moment), just change
to
and see if it works.
I think because of the way you structure your controls, the
ComboBoxis at the same level/scope as thetb:ToolBarControland thetb:ToolBar. That means they all share the sameDataContext, so you don’t really need anyElementNamebinding orRelativeSourcebinding to try to find its parent/ancestor.If you remove
DataContext="{Binding ElementName=myWindow}from thetb:ToolBar, you can even get rid of the prefixDataContextin the binding. And this is really all you need.UPDATE 2 to answer your Edit 3
This is because your
Itemscollection in yourtb:ToolBarusercontrol is just a property. It’s not in the logical and visual tree, and I believeElementNamebinding uses logical tree.That’s why it is not working.
Add to logical tree
I think to add the
Itemsinto the logical tree you need to do two things.First you need to override the
LogicalChildrenin yourtb:ToolBarusercontrol.Then whenever you added a new
tb:ToolBarControlyou need to callGive it a shot.
This WORKS…
After playing around with it a little bit, I think what I showed you above isn’t enough. You will also need to add these
ToolBarControlsto your main window’s name scope to enableElementNamebinding. I assume this is how you defined yourItemsdependency property.In the callback, it is where you add it to the name scope.
Also if you want property inheritance, you will need
I have tested the code and it works fine.