WinUI3ではStyle.Triggersがないので代替手段でマウスオーバー時の背景色変更する

もくじ
https://tera1707.com/entry/2022/02/06/144447#WinUI3

やりたいこと

以前調べた、WPFStyle.Triggerを使ってマウスオーバー時に背景色を変える方法をWinUI3でもやろうとすると、Style.Triggerがなくなって使えなくなっていた。

WinUI3っで、お手軽に掲題のようなことをしたい場合、どうしたらいいのか、調べたい。

前提

  • VisualStudio2022 Community 17.1.4
  • WinUI3.0
  • Windows App SDK 1.0
  • 2022年5月の時点で調査実施

結論

WPFでやっていた、Style.Triggerを使って簡単にマウスオーバー時に背景色を変えるような方法は、WinUI3では見つけられなかった。

代わりに、
例えばボタンの背景色をマウスオーバー時に変えたいのであれば、
generic.xamlから標準のボタンのstyle(とその中のテンプレート)をコピーして、必要なところ(今回であれば、<VisualState x:Name="PointerOver">の色をいじってるあたり)をカスタムするのが、WinUI3では近道だと現時点では思う。

具体的なやり方は、
以前調べたWinUI3でのテーマカラー対応の中でやっている「独自の色ボタンのための作業をする」と「generic.xamlから、標準のボタンのstyleをコピーして、自分のリソースディクショナリにコピーする」を参照。

そのほか、xamlに数行書くだけでそれができるような方法は今のところ見つけられていない。 上の方法は、コピーする量が結構多い、かついじる部分は少なめになるので気持ちよくはないが、わかりやすいといえばわかりやすいやり方なので、個人的には嫌いじゃない。

しらべたことのメモ

以下は、なにかいいやり方がないか、いろいろ調べたときの徒然メモ。


いろいろ代替手段を探しているときにWindows.UI.Xamlの‘FrameworkElement.Triggers‘というのを見つけたのでそれを調べていたら、EventTrigger クラスのドキュメントに、下記のように書いてあった。

Triggers、EventTrigger、Actions、BeginStoryboardは一般的に使用されていません。これらのAPIは、主にMicrosoftSilverlightで元々使用されていたXAMLとの互換性のために存在します。

とのこと。WinUI3では、「Trigger」系はもはや使われてないっぽい。


さらなる代替手段として、VisualStateManager クラス というのが使えそうなにおいがする。→こちら

調べてみる。

調べてみた。
例えばこんな感じで書くと、ボタンをおしたときに色が変わるボタンが出来上がる。

<Page
    x:Class="PageTemplate.BlankPage1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PageTemplate"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 
    <Button Width="100" Height="100" Background="White" Name="aaa">
        <Button.Template>
            <ControlTemplate TargetType="Button">
                <Grid >
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">

                            <VisualStateGroup.Transitions>
                                <VisualTransition To="PointerOver" GeneratedDuration="0:0:3"/>
                            </VisualStateGroup.Transitions>

                            <VisualState x:Name="Normal" />

                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="ButtonBrush" Storyboard.TargetProperty="Color" To="Red" />
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid.Background>
                        <SolidColorBrush x:Name="ButtonBrush" Color="Green"/>
                    </Grid.Background>
                </Grid>
            </ControlTemplate>
        </Button.Template>
    </Button>
</Page>

が、上記のようにControlTemplateを自前でつくると、好きな見た目にはできるが、元のボタンからはかけ離れた見た目になり、 今回調べようとしていた「簡単に、マウスオーバー時の色を変える」から離れてしまう。

どうも、上記をやるのであれば、触っている限りの個人的感触では、
以前調べたWinUI3でのテーマカラー対応の中でやっている「generic.xamlから、標準のボタンのstyleをコピーして、自分のリソースディクショナリにコピーする」をやって、必要なところの色だけを変える、ということをやる方が、ぱっと見のコード量は、標準のstyle(テンプレート)をコピペする分増えてしまうが、やることは簡単&ベースの見た目も元のボタンに近づけることができると感じる。

また、マイクロソフトもそのやり方を推しているように感じる。

※ボタンの見た目をガラッと変えていい場合はなおさら、標準ボタンのstyleを取ってきて、その中のテンプレートを好きにいじってやればいい。

なので、

  • マウスオーバー時のボタンの色を変えたい
  • 標準とは異なる自前のかっこいいボタンをつくりたい

のどの場合も、(styleをちょちょっといじるお手軽さはもう無理とあきらめて)「generic.xamlから、標準のボタンのstyleをコピーして、必要なところをカスタムする」のが、WinUI3では近道だと思った。

参考

FrameworkElement.Triggersプロパティ(Microsoft.UI.Xaml

https://docs.microsoft.com/ja-jp/windows/winui/api/microsoft.ui.xaml.frameworkelement.triggers?view=winui-3.0

Loadedイベント
<EventTrigger>RoutedEventプロパティに何もセットしないと、Loadedがトリガーになるらしい。

https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.frameworkelement.loaded?view=winrt-22000

ストーリーボードの概要
<EventTrigger>にセットするStoryboardの使い方。.net Framework4.xの説明ページっぽいが、ほぼ同じか。

https://docs.microsoft.com/ja-jp/dotnet/desktop/wpf/graphics-multimedia/storyboards-overview?view=netframeworkdesktop-4.8&viewFallbackFrom=netdesktop-6.0

VisualStateManager クラス

https://docs.microsoft.com/ja-jp/uwp/api/windows.ui.xaml.visualstatemanager?view=winrt-18362