c#

【WPF】LabelやTextBlockの文字列を点滅させる方法

せっかくWPFを利用するなら、Windowsフォームでは作りにくいアニメーションを取り入れたいですよね。
今回は、「Label(or TextBlock)を点滅させる」という要件を実装したいと思います。
実開発で「〇〇処理中」などの文字列をぴょこぴょこさせたい機会があったので備忘録。


リソースディクショナリ(style.xaml)の作成

アニメーションの動作をStyleで定義するため、リソースディクショナリを作成します。

①ソリューションエクスプローラーでプロジェクトを右クリック

②「追加」⇒「新しい項目」を選択

③「リソースディクショナリ(WPF)」を選択し、任意の名前に変更し、「追加」を選択
(ここではstyle.xamlとします)

リソースディクショナリ追加
リソースディクショナリ追加


Styleの定義

追加したstyle.xamlが {プロジェクトルート}\ 下にできたと思います。
中身を下記のように定義します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApplication1">

    <!-- 点滅アニメーション定義 -->
    <Storyboard x:Key="FlashStory">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" RepeatBehavior="Forever" AutoReverse="True">
            <LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="1" />
            <LinearDoubleKeyFrame KeyTime="0:0:0.8" Value="0" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

    <!-- Labelスタイル定義 -->
    <Style TargetType="Label" x:Key="LabelFlash">
        <Style.Triggers>
            <EventTrigger RoutedEvent="Label.Loaded">
                <BeginStoryboard Storyboard="{StaticResource FlashStory}" />
            </EventTrigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

ビルドアクションの変更

ソリューションエクスプローラーでstyle.xamlのプロパティを表示し、ビルドアクションを変更します。

なし

Resource

ビルドアクション=Resource
ビルドアクション=Resource

これでソース上でstyle.xamlにアクセスできます。


style.xamlの読み込み

上記でアクセスできるようにしたstyle.xamlを、アプリケーションに読み込ませます。
{プロジェクトルート}\App.xaml をビューデザイナーで編集します。

Application.Resourcesタグの間に、下記記述を追加します。

<ResourceDictionary Source="style.xaml" />

波線が出るようだとファイルを見つけられていないので、パスを再確認してください。

するとこんな感じ。

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="FlashExample.xaml">
    <Application.Resources>
        <ResourceDictionary Source="style.xaml" />
    </Application.Resources>
</Application>

XAMLにコントロールを配置

では実際に使うUIにコントロールを配置します。

<Label x:Name="lblMessage" Content="処理中" Foreground="White" FontSize="22" Background="LightBlue" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40" Style="{StaticResource LabelFlash}" />

大事なところは、↓の部分。

Style="{StaticResource LabelFlash}"

style.xamlに定義したLabel用のアニメーションをスタイルに設定します。

全体ではこんな感じ。

<Window x:Class="WpfApplication1.FlashExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="FlashExample" Height="250" Width="325">
    <Grid>
        <Label x:Name="lblMessage" Content="処理中" Foreground="White" FontSize="22" Background="LightBlue" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="40" Style="{StaticResource LabelFlash}" />
    </Grid>
</Window>

実行

上記XAMLで実行すると。。。
処理中アニメーション

点滅してくれました。

補足

TextBlockの場合

上記サンプルはラベルで実現しましが、TextBlockの場合はstyle.xamlのTargetTypeとRoutedEventを変更すれば実現できます。
こんなイメージ↓

    <!-- TextBlockスタイル定義 -->
    <Style TargetType="TextBlock" x:Key="TextBlockFlash">
        <Style.Triggers>
            <EventTrigger RoutedEvent="TextBlock.Loaded">
                <BeginStoryboard Storyboard="{StaticResource FlashStory}" />
            </EventTrigger>
        </Style.Triggers>
    </Style>

特定の条件で点滅させる場合

サンプルでは、RoutedEvent=”Label.Loaded”としているため、
読み込んだら常に点滅のスタイルが適用されます。
実際の要件では、トリガーや条件によって適用することもあると思いますので、例を掲示します。

例)ラベルの背景色変更時に点滅
①ソース側のプロパティを使用するため、XAMLのヘッダーに↓を追記します。

DataContext="{Binding RelativeSource={RelativeSource Self}}"

②Labelの背景色部分を変更します。

Background="LightBlue"

Background="{Binding LblMessageBackground, NotifyOnTargetUpdated=True}"

③ソース側でXAMLのプロパティ(LblMessageBackground)の記述を追加します。
※プロパティの変更を検知するには、INotifyPropertyChangedを実装する必要があります。

using System.Windows;
using System.Windows.Media;
using System.ComponentModel;

namespace WpfApplication1
{
    public partial class FlashExample : INotifyPropertyChanged
    {
        public FlashExample()
        {
            InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private Brush _lblMessageBackground;
        public Brush LblMessageBackground
        {
            get
            {
                return _lblMessageBackground;
            }
            set
            {
                _lblMessageBackground = value;
                OnPropertyChanged("LblMessageBackground");
            }
        }

        protected virtual void OnPropertyChanged(string name)
        {
            if (PropertyChanged == null) return;

            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            LblMessageBackground = new SolidColorBrush(Colors.Red);
        }
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です