6

私はWPFを初めて使用するので、重要なものが欠けている可能性がありますが、実験して次の現象の説明を考え出そうとしましたが、役に立ちませんでした。基本的に、次のコードが機能します (アニメーションを表示します)。

    <Window.Resources>
    <Storyboard x:Key="LoadStoryBoard"
AutoReverse="True"
RepeatBehavior="Forever">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="button1" 
                Storyboard.TargetProperty="(Button.Opacity)">
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
...
<Button x:Name="button1" Grid.Column="0" Grid.Row="1" Style="{StaticResource Load}">
<Button.Triggers>
    <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
            </EventTrigger>
</Button.Triggers>
</Button>

ただし、次の Load Style にイベントトリガーを配置しようとすると、アニメーションが表示されなくなります。

    <Window.Resources>
    <Storyboard x:Key="LoadStoryBoard"
AutoReverse="True"
RepeatBehavior="Forever">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="button1" 
                Storyboard.TargetProperty="(Button.Opacity)">
            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
...
<Style x:Key="Load" TargetType="Button">
...
<Style.Triggers>
    ...
    <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
            </EventTrigger>
</Style.Triggers>
</Style>
4

2 に答える 2

3

が機能していないことは正しいですが、セクションEventTriggerで宣言されているためではありません。これを確認するには、スタイルがまだ機能しない宣言にResources直接移動します。Button

<Button x:Name="button1" Grid.Column="0" Grid.Row="1">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.Loaded">
                    <BeginStoryboard Storyboard="{StaticResource LoadStoryBoard}" />
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Animationただし、セクションからの宣言を移動すると、Resources再び機能します。

<Button x:Name="button1" Grid.Column="0" Grid.Row="1">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Button.Loaded">
                    <BeginStoryboard>
                        <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Button.Opacity)">
                                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

そのため、問題は、イベントが発生するまでに準備ができていないセクションでStoryboard宣言されていることに関係しているようです。この投稿に記載されている同様の問題があります。ResourcesLoaded

ただし、さらに混乱させるために、 の完全な宣言をセクションで宣言されAnimationた に入れると、次のようになります。StyleResourcesStyle

<Window.Resources>
    <Style x:Key="Load" TargetType="Button">
        <Style.Triggers>
            <EventTrigger RoutedEvent="Button.Loaded">
                <BeginStoryboard>
                    <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Button.Opacity)">
                            <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0.4" />
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Button x:Name="button1" Grid.Column="0" Grid.Row="1" Style="{StaticResource Load}" />

なぜこれが起こるのかを推測することはできますが、すべてがそのようになっている理由を本当に知っているWPF開発者はほとんどいないと思います...特定の宣言方法が機能する場合は、それを使用してそうでない場合は、別のものを試してください。

バックグラウンド

WPF では、定義できる場所が 4 つありますTriggersStyle.TriggersControlTemplate.TriggersDataTemplate.TriggersおよびFrameworkElement.Triggers(例: Button.Triggers)。

基本的に、FrameworkElement.Triggers TriggerCollectionタイプのトリガーのみを受け入れるという点で、 には大きな欠陥がありEventTriggerます。これは、MSDN のFrameworkElement.Triggers プロパティページで確認できます。ここでは、このプロパティが受け入れることができるものについて次の定義が示されています。

1 つ以上の定義された EventTrigger 要素。このような各トリガーには、有効なストーリーボード アクションと参照が含まれている必要があります。このコレクションは、ページのルート要素でのみ確立できることに注意してください。

他のトリガー プロパティの MSDN プロパティ ページでは、 0 個以上の TriggerBase オブジェクト、または1 個以上の TriggerBase オブジェクトを受け入れることができることがそれぞれアナウンスされています。

さらに、さまざまなトリガーが従う明確なルールがあります。統一されたアプローチは、WPF の新規参入者を確かに助けたでしょう。FrameworkElement.Triggers プロパティページから:

このプロパティでは、この要素で使用されているスタイルの一部として存在するトリガーを調べることはできません。マークアップまたはコードのいずれかで文字通りコレクションに追加されたトリガーのコレクションのみを報告します。要素には通常、(たとえばテンプレートを介して) デフォルトでそのような要素が存在することはありません。代わりに、コントロール合成からのトリガーがスタイルで確立されるのがより一般的です。

動作 (および、どの要素の宣言された Triggers コレクションからどの効果が発生したかを確立しようとすること) に関しては、トリガー条件とトリガー効果の両方がこの要素上にあるか、論理ツリー内のその子要素上にある可能性があります。Loaded などのライフタイム イベントを使用してこのコレクションを取得する場合、子要素のトリガーがまだ完全に読み込まれていない可能性があり、コレクションは実際の実行時よりも小さくなることに注意してください。

要素で確立されたトリガーのコレクションは、プロパティ トリガー (Trigger) ではなく、EventTrigger のみをサポートすることに注意してください。プロパティ トリガーが必要な場合は、これらをスタイルまたはテンプレート内に配置し、そのスタイルまたはテンプレートを Style プロパティを介して直接、または暗黙的なスタイル参照を介して間接的に要素に割り当てる必要があります。

MSDNのDataTemplate.Triggers プロパティページから:

データ テンプレート内でトリガーを作成する場合、トリガーのセッターは、データ テンプレートのスコープ内にあるプロパティを設定する必要があります。それ以外の場合は、データを含む型を対象とするスタイルを使用してトリガーを作成する方が適切な場合があります。たとえば、ListBox コントロールをバインドしている場合、コンテナーは ListBoxItem オブジェクトです。トリガーを使用して DataTemplate の範囲外のプロパティを設定する場合は、ListBoxItem スタイルを作成し、そのスタイル内にトリガーを作成する方が適切な場合があります。

残念ながら、このすべての追加情報は、リソースでアニメーション リソースが機能しない理由についての質問に実際には答えませんが、領域全体が少し複雑で厄介な領域であるStyleことがわかると思います。Trigger私自身は専門家ではないので、Triggers を宣言するのに有効な方法を使用する傾向があります。

それが何らかの形で役立つことを願っています。

于 2013-07-23T09:56:38.090 に答える