C# 控制用户控件';仅使用XAML从WPF中的父窗口创建脚本

C# 控制用户控件';仅使用XAML从WPF中的父窗口创建脚本,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,我创建了一个非常简单的测试应用程序,试图解决一位同事向我描述的这个问题。他能够在C#中触发它,但我相信他需要更通用的解决方案,并希望它严格地在XAML中完成。问题是:如何触发UserControl内部的故事板开始响应包含窗口中控件上的事件(父控件不必是窗口,它可以是页面或其他UserControl…为了简单起见,我使用窗口)。所以,我最好的例子是,您有一个带有按钮的窗口和一个UserControl实例。您希望按钮的单击事件触发UserControl内部的故事板开始 在UserControl本身内

我创建了一个非常简单的测试应用程序,试图解决一位同事向我描述的这个问题。他能够在C#中触发它,但我相信他需要更通用的解决方案,并希望它严格地在XAML中完成。问题是:如何触发UserControl内部的故事板开始响应包含窗口中控件上的事件(父控件不必是窗口,它可以是页面或其他UserControl…为了简单起见,我使用窗口)。所以,我最好的例子是,您有一个带有按钮的窗口和一个UserControl实例。您希望按钮的单击事件触发UserControl内部的故事板开始

在UserControl本身内部,序列图像板被声明为一个具有MyStoryboard键的资源。我创建了一个带有EventTrigger的按钮,以显示我可以通过引用绑定表达式来触发情节提要。以下是my UserControl的完整XAML:

<UserControl x:Class="UserControlStoryboard.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<UserControl.Resources>
    <Storyboard x:Key="MyStoryboard">
        <ColorAnimation Storyboard.TargetName="grid" Storyboard.TargetProperty="(Grid.Background).Color" From="CadetBlue" To="White" Duration="0:0:2" />
    </Storyboard>
</UserControl.Resources>
<Grid Background="CadetBlue" x:Name="grid">
    <Button Content="Press Me" Height="50">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <BeginStoryboard.Storyboard>
                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" Path="Resources[MyStoryboard]" />
                    </BeginStoryboard.Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>            
</Grid>

我希望,因为我能够告诉故事板从引用绑定表达式开始,所以我应该能够在包含这个UserControl作为子元素的窗口中执行完全相同的操作。但我似乎不知道如何在父窗口中获取对情节提要的引用。仅在XAML中不可能实现这一点吗

我的测试项目中的父窗口只有一个按钮和这个UserControl的一个实例。如果可能的话,哪一个元素可以让我添加一个EventTrigger,其中事件的源是按钮,触发动作告诉UserControl的故事板开始


谢谢。

您可以使用StaticResource访问故事板。您只需将资源分配给BeginStroyboard上的故事板

<BeginStoryboard Storyboard="{StaticResource MyStoryboard}">
</BeginStoryboard>

我将代码更改为以下内容,当您按下按钮时,它将为您启动故事板。希望这有帮助

    <UserControl.Resources>
    <Storyboard x:Key="MyStoryboard">
        <ColorAnimation Storyboard.TargetName="grid" Storyboard.TargetProperty="(Grid.Background).Color" From="CadetBlue" To="White" Duration="0:0:2" />
    </Storyboard>
</UserControl.Resources>
<Grid Background="CadetBlue" x:Name="grid">
    <Button Content="Press Me" Height="50">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard Storyboard="{StaticResource MyStoryboard}">
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>
</Grid>

使用纯Xaml可能不是一个好方法

你可以:

  • 在UserControl上创建一个带有按钮的dependency属性,然后可以绑定到它
  • 做一个疯狂的转换器,遍历你的视觉树,寻找特别的东西

两者都需要一些C#,所以我不知道上面的任何一项是否是您想要的。

我认为在UserControl中响应外部事件的想法不是很安全。在UserControl中,您希望只对控件中生成的事件作出反应

你能把形势扭转过来,做以下几件事吗

  • 公开需要作为依赖项属性设置动画的UC属性(本例中为背景)
  • 在父窗口上创建EventTrigger和Storyboard

我有一个非常类似的情况,你有没有找到解决方案?不幸的是,没有。这个问题是两年前提出的。从那以后,我用模板绑定在父控件和子控件之间来回通信,做了一些非常粗糙的事情。现在有了这样的经验,我实际上更倾向于更直接的C#方法。在xaml、绑定、视图模型等方面,我看到的技巧越多,我就越畏缩……这会成为一场巨大的调试噩梦。“我认为在UserControl中响应外部事件的想法并不安全。”。为什么?这个概念可以追溯到响应主机容器中环境属性的ActiveX控件或ActiveX文档。当然,现在我们谈论的是WPF,但我认为它的概念是相同的