I have the following routed event:

public static readonly RoutedEvent FakeEvent = EventManager.RegisterRoutedEvent(
    "Fake", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(MainWindow));
public event RoutedEventHandler Fake
{
    add { AddHandler(FakeEvent, value); }
    remove { RemoveHandler(FakeEvent, value); }
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    RoutedEventArgs newEventArgs = new RoutedEventArgs(MainWindow.FakeEvent);
    RaiseEvent(newEventArgs);
}

I have the following XAML:

<Window.Resources>

    <Style TargetType="{x:Type TextBlock}"
       xmlns:local="clr-namespace:WpfApplication1">
        <Setter Property="Margin" Value="10" />
        <Setter Property="Background" Value="Red" />
        <Style.Triggers>
            <EventTrigger RoutedEvent="local:MainWindow.Fake">
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation To="Blue" Duration="0:0:1"
                            Storyboard.TargetProperty="Background.Color" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>

</Window.Resources>

<StackPanel>
    <Button Click="Button_Click">Raise Event</Button>
    <TextBlock>Hello World</TextBlock>
    <TextBlock>Hello World</TextBlock>
    <TextBlock>Hello World</TextBlock>
    <TextBlock>Hello World</TextBlock>
    <TextBlock>Hello World</TextBlock>
    <TextBlock>Hello World</TextBlock>
</StackPanel>

My goal is that the window's routed event would cause the storyboard to fire for all the TextBlocks by using a reusable, generic style. However, raising the routed event (by clicking the button) results in nothing occurring (no error, just nothing). Not sure what's wrong.

What is the correct approach to this?

有帮助吗?

解决方案

You might have misunderstood how tunneling works:

Tunneling: Initially, event handlers at the element tree root are invoked. The routed event then travels a route through successive child elements along the route, towards the node element that is the routed event source (the element that raised the routed event).

Here the event will travel from the root, the window, to the source, also the window, it will never come across the TextBlocks. You would either need to raise the event on all of them or listen to the event on the window, unfortunately you cannot use EventTrigger.SourceName in styles. Sadly i do not know of any good solution to this...

(You could use an EventSetter to handle the Loaded event of the TextBlocks to then listen to the event on the window and re-raise it locally (you will want to change the routing strategy or you will get a stack overflow exception if you do not check where the event came from), it might be questionable if that is a good idea)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top