左クリックでFlyoutを表示できるToggleボタンを作る

WInUI3関連記事

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

やりたいこと

普通のボタン(Microsoft.UI.Xaml.Controls.Button)にはFlyoutプロパティがあって、そこにFlyoutを入れてやると、 クリックしたときにフライアウトを出すことができる。

今回、トグルボタン(Microsoft.UI.Xaml.Controls.ToggleButton)でもクリックしたときにフライアウトを出したいのだが、トグルボタンには Flyoutプロパティがなく、右クリックしたときに出るFlyoutをセットするためのContextFlyoutしかない。

ContextFlyoutをうまく使って、普通の(左クリックして出る)Flyoutっぽく動かせないか、やってみる。

前提

  • VisualStudio2022 Community 17.1.4
  • WinUI3
  • Windows App SDK 1.0

やり方

下記のような感じでやってみた。

  • ToggleButtonを継承したクラスを作成し、
    • OnToggle()をオーバーライドして、親クラスのOnToggleの処理(base.OnToggle())を行わないようにすることで、通常のToggleボタンを左クリックしたときのトグル(ONになったりOFFになったりする)動作が行われないようにする。
    • 代わりに、OnToggle()では、ContextFlyoutを自分の場所に表示する処理を行う。
    • Toggle動作はFlyoutの中に入っているRadioButtonのONOFFを見て行うようにする。
  • 画面のxamlでは、作ったクラスのContextFlyoutに、出したいフライアウトをセットしておく。

サンプルコード

フライアウトできるトグルボタンのコード

public class FlyoutToggleButton : ToggleButton
{
    protected override void OnToggle()
    {
        //base.OnToggle();
        this.ContextFlyout.ShowAt(this);
    }
}

それを使う画面

<Grid>
    <local:FlyoutToggleButton Content="クリック時にFlyoutを出せるトグルボタン"
                              IsChecked="{Binding IsChecked, ElementName=radio1}">
        <local:FlyoutToggleButton.ContextFlyout>
            <Flyout>
                <StackPanel>
                    <RadioButton x:Name="radio1" Content="選択1"/>
                    <RadioButton x:Name="radio2" Content="選択2"/>
                </StackPanel>
            </Flyout>
        </local:FlyoutToggleButton.ContextFlyout>
    </local:FlyoutToggleButton>
</Grid>

動作イメージ

f:id:tera1707:20220415235141p:plain

f:id:tera1707:20220415235153p:plain

参照

Button

docs.microsoft.com

ToggleButton

docs.microsoft.com