I have a ListBox
which binds to a child collection on a ViewModel. The listbox items are styled in a datatemplate based on a property on the parent ViewModel:
<Style x:Key="curveSpeedNonConstantParameterCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified,
ElementName=someParentElementWithReferenceToRootDataContext}"
Value="True">
<Setter Property="Control.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
I get the following output error:
System.Windows.Data Error: 39 : BindingExpression path error:
'CurveSpeedMustBeSpecified' property not found on
'object' ''BindingListCollectionView' (HashCode=20467555)'.
BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified;
DataItem='Grid' (Name='nonConstantCurveParametersGrid');
target element is 'TextBox' (Name='');
target property is 'NoTarget' (type 'Object')
So if I change the the binding expression to "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified"
it works, but only as long as the datacontext of the parent user control is a BindingListCollectionView
. This is not acceptable because the rest of the user control binds to the properties of the CurrentItem
on the BindingList
automatically.
How can I specify the binding expression inside the style so that it works regardless of the parent data context being a collection view or a single item?
the issue is that a DataTemplate isn't part of an element its applied to it.
this means if you bind to the template you're binding to something that has no context.
however if you put a element inside the template then when that element is applied to the parent it gains a context and the binding then works
so this will not work
but this works perfectly
because after the datatemplate is applied the groupbox is placed in the parent and will have access to its Context
so all you have to do is remove the style from the template and move it into an element in the template
note that the context for a itemscontrol is the item not the control ie ComboBoxItem for ComboBox not the ComboBox itself in which case you should use the controls ItemContainerStyle instead
I had problems with the relative source in Silverlight. After searching and reading I did not find a suitable solution without using some additional Binding library. But, here is another approach for gaining access to the parent DataContext by directly referencing an element of which you know the data context. It uses
Binding ElementName
and works quite well, as long as you respect your own naming and don't have heavy reuse oftemplates
/styles
across components:This also works if you put the button into
Style
/Template
:At first I thought that the
x:Names
of parent elements are not accessible from within a templated item, but since I found no better solution, I just tried, and it works fine.You can use
RelativeSource
to find the parent element, like this -See this SO question for more details about
RelativeSource
.RelativeSource vs. ElementName
These two approaches can achieve the same result,
RelativeSrouce
This method looks for a control of a type Window (in this example) in the visual tree and when it finds it you basically can access it's
DataContext
using thePath=DataContext....
. The Pros about this method is that you don't need to be tied to a name and it's kind of dynamic, however, changes made to your visual tree can affect this method and possibly break it.ElementName
This method referes to a solid static
Name
so as long as your scope can see it, you're fine.You should be sticking to your naming convention not to break this method of course.The approach is qute simple and all you need is to specify aName="..."
for your Window/UserControl.Although all three types (
RelativeSource, Source, ElementName
) are capable of doing the same thing, but according to the following MSDN article, each one better be used in their own area of specialty.How to: Specify the Binding Source
Find the brief description of each plus a link to a more details one in the table on the bottom of the page.
I was searching how to do something similar in WPF and I got this solution:
I hope this works for somebody else. I have a data context which is set automatically to the ItemsControls, and this data context has two properties:
MyItems
-which is a collection-, and one command 'CustomCommand'. Because of theItemTemplate
is using aDataTemplate
, theDataContext
of upper levels is not directly accessible. Then the workaround to get the DC of the parent is use a relative path and filter byItemsControl
type.