Wpf 绑定到情节提要上的附加行为
我已经为情节提要创建了一个附加的依赖属性,目的是使我能够在触发情节提要完成事件时调用ViewModel上的方法:Wpf 绑定到情节提要上的附加行为,wpf,data-binding,xaml,dependency-properties,storyboard,Wpf,Data Binding,Xaml,Dependency Properties,Storyboard,我已经为情节提要创建了一个附加的依赖属性,目的是使我能够在触发情节提要完成事件时调用ViewModel上的方法: public static class StoryboardExtensions { public static ICommand GetCompletedCommand(DependencyObject target) { return (ICommand)target.GetValue(CompletedCommandProperty);
public static class StoryboardExtensions
{
public static ICommand GetCompletedCommand(DependencyObject target)
{
return (ICommand)target.GetValue(CompletedCommandProperty);
}
public static void SetCompletedCommand(DependencyObject target, ICommand value)
{
target.SetValue(CompletedCommandProperty, value);
}
public static readonly DependencyProperty CompletedCommandProperty =
DependencyProperty.RegisterAttached(
"CompletedCommand",
typeof(ICommand),
typeof(StoryboardExtensions),
new FrameworkPropertyMetadata(null, OnCompletedCommandChanged));
static void OnCompletedCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
Storyboard storyboard = target as Storyboard;
if (storyboard == null) throw new InvalidOperationException("This behavior can be attached to Storyboard item only.");
storyboard.Completed += new EventHandler(OnStoryboardCompleted);
}
static void OnStoryboardCompleted(object sender, EventArgs e)
{
Storyboard item = ... // snip
ICommand command = GetCompletedCommand(item);
command.Execute(null);
}
}
然后我尝试在XAML中使用它,并使用绑定语法:
<Grid>
<Grid.Resources>
<Storyboard x:Key="myStoryboard" my:StoryboardExtensions.CompletedCommand="{Binding AnimationCompleted}">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:5" />
</Storyboard>
<Style x:Key="myStyle" TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=QuestionState}" Value="Correct">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource myStoryboard}" />
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Label x:Name="labelHello" Grid.Row="0" Style="{StaticResource myStyle}">Hello</Label>
</Grid>
你好
此操作失败,但出现以下异常:
发生System.Windows.Markup.XamlParseException异常
Message=“无法将属性“Style”中的值转换为类型为“System.Windows.Style”的对象。无法冻结此情节提要时间线树以便跨线程使用。标记文件“TestWpfApp;component/window1.xaml”中的对象“labelHello”处出错
有没有办法让绑定语法与情节提要的附加ICommand属性一起工作?这是出于设计考虑。如果您有一个可冻结的对象放入样式中,样式将被冻结以允许跨线程访问。但您的绑定本质上是一个表达式,这意味着它不能被冻结为数据绑定是单线程的 如果需要执行此操作,请将触发器放在框架元素下的样式之外,而不是放在样式中。您可以在Grid.Triggers部分执行此操作。这确实有点糟糕,因为您的样式不再完整,您必须复制触发器,但它是WPF中的“按设计”功能
MSDN社交论坛上的完整答案是。您可以创建一个新的Freezable派生类,以将情节提要作为垫片启动。将该垫片对象上的属性绑定到情节提要名称。这样,您就不必复制触发器或将其存储在样式之外。为了解决此问题,我创建了一组附加属性,称为故事板助手()。我放弃了将它们附加到故事板本身的尝试,现在附加到任何(任意)框架元素,以便在情节提要完成时调用my ViewModel上的ICommand,以及绑定到my ViewModel上的特定事件以启动情节提要。第三个附加属性指定我们正在处理的情节提要:
<FrameworkElement
my:StoryboardHelpers.Storyboard="{StaticResource rightAnswerAnimation}"
my:StoryboardHelpers.Completed="{Binding CompletedCommand}"
my:StoryboardHelpers.BeginEvent="{Binding StartCorrectAnswer}" />
但是Grid.Triggers不接受DataTrigger,只接受EventTriggerHmm,这会使它更复杂。现在还不太确定。关于可自由化对象的想法仍然有效,但有一个解决方案?不确定。请尝试以下链接: