WPF——it';它一定比我容易';我成功了

WPF——it';它一定比我容易';我成功了,wpf,button,triggers,textblock,Wpf,Button,Triggers,Textblock,我正在花最宝贵的时间来解决这个问题:假设我有两个按钮和三个文本块。我希望任何一个按钮都能在所有文本块上触发一个简单的故事板。目前,我正在尝试定义一个包含故事板的通用文本块样式,然后触发器来自任何按钮单击。这是我最接近的一次,但应用程序在启动时崩溃了…我在这里没有错什么: <Window.Resources> <Style TargetType="TextBlock" > <Setter Property="Foreground" Value="Blue"

我正在花最宝贵的时间来解决这个问题:假设我有两个按钮和三个文本块。我希望任何一个按钮都能在所有文本块上触发一个简单的故事板。目前,我正在尝试定义一个包含故事板的通用文本块样式,然后触发器来自任何按钮单击。这是我最接近的一次,但应用程序在启动时崩溃了…我在这里没有错什么:

<Window.Resources>

<Style TargetType="TextBlock" >
    <Setter Property="Foreground" Value="Blue" />
    <Style.Resources>
        <Storyboard x:Key="TextBlockOpacity" Storyboard.TargetProperty="Opacity">
            <DoubleAnimation From="0" To="1" />
        </Storyboard>
    </Style.Resources>      
</Style>


如果您“专用”按钮来更改不透明度,您可以利用其
数据上下文
并设置动画。然后只需将元素的
不透明度
绑定到
数据上下文

(我还对xaml进行了一些重构)


0
文本1
文本2
还要注意一件事——如果您希望最小化代码,并使其在xaml中实现,那么可以使用这种方法。您的方法将匹配整个窗口的
不透明度。这就是为什么在上面的代码中,文本块绑定到按钮的
DataContext
,该按钮本身是动画的

当然,不需要绑定到公共值(DataContext)就可以实现,但随后需要重复X动画(因为需要设置X TargetNames)。上述方法更易于扩展和维护

编辑


添加了另一个按钮和多样性列表框:)

在示例中,您将样式内的情节提要定义为资源,但随后尝试将其作为窗口资源访问。尝试将情节提要声明移动到Window.Resources,然后引用样式中的情节提要


我不知道它是否能满足您的需要,但我会从这里开始。

基于kek444的Xaml only解决方案,我提供了一个稍微改进的版本,它不依赖按钮的DataContext,并且可以有多个触发器

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WpfApplication1.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">
    <Window.Resources>
        <UIElement x:Key="OpacityCounter" Opacity="0"/>
        <Style TargetType="TextBlock">
            <Setter Property="Opacity" Value="{Binding Source={StaticResource OpacityCounter}, Path=Opacity}" />
        </Style>
        <Storyboard x:Key="OnClick1">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.Target="{StaticResource OpacityCounter}" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1">
            <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button2">
            <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
        </EventTrigger>
    </Window.Triggers>

    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="button1" Width="131" Height="37" Content="Button 1" Margin="0,0,0,22"/>
                <Button x:Name="button2" Width="131" Height="37" Content="Button 2" Margin="0,0,0,22"/>
            </StackPanel>
            <TextBlock x:Name="textBlock" Height="27" Text="TextBlock 1" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock1" Height="27" Text="TextBlock 2" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock2" Height="27" Text="TextBlock 3" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock3" Height="27" Text="TextBlock 4" TextWrapping="Wrap" />
        </StackPanel>
    </Grid>
</Window>

要将ListBox用作触发器机制(如果您在某处有一个名为“listbox1”的ListBox,请将以下内容添加到Window.Triggers:

<EventTrigger RoutedEvent="Selector.SelectionChanged" SourceName="listbox1">
    <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>

或者,要触发特定的ListBoxItem,您需要(其中item1是命名的ListBoxItem):



你能试着给故事板起个名字,然后看看在代码背后你是否能正确地开始()它?你在这里问同样的问题:还是你在寻找一个2按钮点击触发器?我想有人w/代表需要将这个问题与我在上面的评论中提到的问题结合起来。这很好!我想避免将UIElements创建为资源,但人们应该选择更适合他们的方法。不过,将这种方法称为im基于它不使用DataContext并且支持多个触发器这一事实进行证明有点不公平。在DataContext上使用resource UIElement只是个人喜好的问题;而且两种解决方案都支持多个触发器。否则,做得不错。;)好的…现在让它稍微复杂一点…我不是真的试图触发一个按钮,而是从一个列表框中触发一个ListBoxItem更改,它位于StackPanel中,在一个边框中,在主窗口中的一个网格中。我已经尝试了几个小时,但无法获得正确的RoutedEvent…所有ListBoxItem事件都会给出一个关于类被密封或其他的错误…我只是称之为改进,因为它不需要为每个触发机制(即按钮)提供单独的DataContext。我不是有意冒犯。没关系,没有冒犯,只是想指出。您应该注意,不需要多个DataContext。为了完整性,我对示例进行了一些扩展。@unknown(google):出现错误是因为程序集不是为访问新资源而生成的。它应该在构建后工作。好吧,我一直在围绕这个问题运行,但归根结底是名称范围。我有一个列表框,我想触发文本块上的动画,但它们不在同一名称范围内,因此如果我将序列图像板放在Windows.Resources中,则列表框触发器可以找到序列图像板,但序列图像板找不到文本块的TargetName。如果我将情节提要放入Grid.Resource(文本块所在的位置),那么ListBox更改触发器将找不到情节提要。是否有一些命名约定我可以用来跨越名称范围?啊!谢谢
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WpfApplication1.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">
    <Window.Resources>
        <UIElement x:Key="OpacityCounter" Opacity="0"/>
        <Style TargetType="TextBlock">
            <Setter Property="Opacity" Value="{Binding Source={StaticResource OpacityCounter}, Path=Opacity}" />
        </Style>
        <Storyboard x:Key="OnClick1">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.Target="{StaticResource OpacityCounter}" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                <SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1">
            <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button2">
            <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
        </EventTrigger>
    </Window.Triggers>

    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="button1" Width="131" Height="37" Content="Button 1" Margin="0,0,0,22"/>
                <Button x:Name="button2" Width="131" Height="37" Content="Button 2" Margin="0,0,0,22"/>
            </StackPanel>
            <TextBlock x:Name="textBlock" Height="27" Text="TextBlock 1" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock1" Height="27" Text="TextBlock 2" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock2" Height="27" Text="TextBlock 3" TextWrapping="Wrap" />
            <TextBlock x:Name="textBlock3" Height="27" Text="TextBlock 4" TextWrapping="Wrap" />
        </StackPanel>
    </Grid>
</Window>
<EventTrigger RoutedEvent="Selector.SelectionChanged" SourceName="listbox1">
    <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ListBoxItem.Selected" SourceName="item1">
    <BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>