I searched for this Problem on Stackoverflow, but in my opinion the other Posts do not cover this question.
In my Custom Control i am using a Visual State Manager. Inside the Visual State Manager there is an Animation that Animates the Height of an Element. When i try to bind to the Controls Properties i get following Error on StartUp:
Additional information: Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType=MyNameSpace.MyControl, AncestorLevel='1''. BindingExpression:Path=ActualHeight; DataItem=null; target element is 'DoubleAnimation' (HashCode=562002); target property is 'To' (type 'Nullable`1')
My Control looks like this:
<Style TargetType="{x:Type local:MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<Grid x:Name="RootGrid" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="someElement"
Storyboard.TargetProperty="Height"
From="0"
To="{Binding RelativeSource={RelativeSource AncestorType=local:MyControl}, Path=CustomControlProperty}"
Duration="0:0:.7" />
...
I tried all ways of Bindings, but it seems that the Animations always takes itself as Scope.
Thanks for your help again.
I was able to do this with a BindingProxy. I find binding proxies to be nonintuitive. Sometimes they work on the first shot; this one took a little trial and error. Also, they're a little bit of a hail-mary workaround.
XAML:
<Grid
x:Name="RootGrid"
>
<Grid.Resources>
<!--
When defined in ControlTemplate.Resources, this failed.
TemplateBinding failed too.
-->
<local:BindingProxy
x:Key="CustomControlPropertyProxy"
Data="{Binding CustomControlProperty, RelativeSource={RelativeSource TemplatedParent}}"
/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="someElement"
Storyboard.TargetProperty="Height"
From="0"
To="{Binding Data, Source={StaticResource CustomControlPropertyProxy}}"
Duration="0:0:5"
/>
</Storyboard>
C# (stolen, not for the first time, from this answer):
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy));
}
Here's another variant of the XAML, in case you end up binding animation properties to more than one property of the templated parent:
<Grid
x:Name="RootGrid"
>
<Grid.Resources>
<local:BindingProxy
x:Key="TemplatedParentProxy"
Data="{Binding ., RelativeSource={RelativeSource TemplatedParent}}"
/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="someElement"
Storyboard.TargetProperty="Height"
From="0"
To="{Binding Data.CustomControlProperty, Source={StaticResource TemplatedParentProxy}}"
Duration="0:0:5"
/>
</Storyboard>
After ruling out TemplateBinding and {RelativeSource TemplatedParent}, my next guess was to bind RootGrid.Tag to CustomControlProperty and use To="{Binding Tag, ElementName=RootGrid}". That did not work. While intellisense knew about RootGrid in the XAML designer, the Binding couldn't find RootGrid at runtime:
<DoubleAnimation
Storyboard.TargetName="someElement"
Storyboard.TargetProperty="Height"
From="0"
To="{Binding Tag, ElementName=RootGrid, PresentationTraceSources.TraceLevel=High}"
Duration="0:0:1"
/>
Debug trace:
System.Windows.Data Warning: 67 : BindingExpression (hash=15221148): Resolving source
System.Windows.Data Warning: 69 : BindingExpression (hash=15221148): Framework mentor not found
System.Windows.Data Warning: 67 : BindingExpression (hash=15221148): Resolving source (last chance)
System.Windows.Data Warning: 69 : BindingExpression (hash=15221148): Framework mentor not found
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Tag; DataItem=null; target element is 'DoubleAnimation' (HashCode=44950942); target property is 'To' (type 'Nullable`1')
That "governing FrameworkElement or FrameworkContentElement" jazz is the essential problem with all of the other approaches as well. That's where binding proxies come in: Resource lookup isn't limited by that visual tree parent chain stuff.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With