我在Stackoverflow上搜索了这个问题,但在我看来,其他帖子没有涵盖这个问题。
在我的自定义控件中,我使用的是Visual State Manager。在可视状态管理器内部有一个动画,可以动画元素的高度。当我尝试绑定到控件属性时,我在启动时遇到以下错误:
其他信息:找不到引用'RelativeSource FindAncestor,AncestorType = MyNameSpace.MyControl,AncestorLevel ='1'的绑定源。 BindingExpression:路径=的ActualHeight;的DataItem = NULL; target元素是'DoubleAnimation'(HashCode = 562002); target属性为'To'(类型'Nullable`1')
我的控件看起来像这样:
<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" />
...
我尝试过Bindings的所有方法,但似乎Animations总是将自己视为Scope。
再次感谢您的帮助。
答案 0 :(得分:3)
我能够做到with a BindingProxy
。我发现绑定代理是非直观的。有时他们会在第一次拍摄时工作;这个尝试了一点试验和错误。此外,他们是一个有点冰雹的解决方法。
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#(被盗,不是第一次,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));
}
以下是XAML的另一种变体,以防您最终将动画属性绑定到模板化父级的多个属性:
<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>
在排除TemplateBinding
和{RelativeSource TemplatedParent}
之后,我的下一个猜测是将RootGrid.Tag
绑定到CustomControlProperty
并使用To="{Binding Tag, ElementName=RootGrid}"
。那没用。虽然intellisense知道XAML设计器中的RootGrid
,但Binding
在运行时找不到RootGrid
:
<DoubleAnimation
Storyboard.TargetName="someElement"
Storyboard.TargetProperty="Height"
From="0"
To="{Binding Tag, ElementName=RootGrid, PresentationTraceSources.TraceLevel=High}"
Duration="0:0:1"
/>
调试跟踪:
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')
“管理FrameworkElement或FrameworkContentElement”爵士乐也是所有其他方法的基本问题。这就是绑定代理进入的地方:资源查找不受可视树父链的限制。
答案 1 :(得分:0)
编辑我意识到我的答案毕竟不起作用。
[...]
To
的{{1}}属性和From
属性无法成为 绑定,因为那些属性需要冻结 (不可更改)动画可以工作。因此请使用特定颜色代替绑定。
这表明某些动画元素不应该通过动态属性进行更改。我实际上并不知道这是适用于所有动画还是仅适用于特定的子集。
因此,考虑到@EdPlunkett的回答,可能值得研究一下,后续的属性更改是否实际上反映在动画中而没有错误。
如果您需要更多绑定复杂性,则应使用ColorAnimation
进行单向绑定或{TemplateBinding CustomControlProperty}
,而不是尝试通过其他方式查找模板化控件。