WinUI3 メモ Dialog - DrumMidiEditor/DrumMidiEditorApp GitHub Wiki

ShowDialog の代わり

image

CompactOverlayPresenter,OverlappedPresenterを使用して
WindowsFormのShowDialog で制御できないかと思ったが上手くいかなかった。

上手くいかなかったのは
Windowのインスタンスを new() で作成していたことが原因なのかも。
AppWindow.Create を使用すれば行けるのかも?(未確認)

⇒winui3 では、ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
 がサポートされていない模様。作成したウィンドウにコンテンツ(ページ)が設定できない・・・

基本的には、ContentDialog の Content 項目に
Page(入力内容) を設定して表示するのが正しいのかな?

  • 非同期処理になるので後続処理に注意が必要。
  • 縦横のサイズは指定できず、幅も狭いので入力項目が多い場合は使えない
var page = new PageInputBpm
{
    Bpm = info_new.Bpm
};

XamlHelper.InputDialogYesCancelAsync
    (
        Content.XamlRoot,
        ResourcesHelper.GetString( "LabelBpm" ),
        page,
        new(() =>
        {
            // OKボタン押下時の後続処理
        })
    );
public static void InputDialogOkCancelAsync( XamlRoot aContentXamlRoot, string aTitle, object aPageContent, Action aAction )
    => InputDialogOkCancelAsync
        (
            aContentXamlRoot,
            ResourcesHelper.GetString( "Dialog/Input" ),
            aPageContent,
            ResourcesHelper.GetString( "Dialog/Ok" ),
            ResourcesHelper.GetString( "Dialog/Cancel" ),
            aAction
        );

public async static void InputDialogYesCancelAsync( XamlRoot aContentXamlRoot, string aTitle, object aPageContent, string aYesButtonText, string aCancelButtonText, Action aAction )
{
    var cd = new ContentDialog
    {
        Title               = aTitle,
        Content             = aPageContent,
        PrimaryButtonText   = aYesButtonText,
        CloseButtonText     = aCancelButtonText,
        XamlRoot            = aContentXamlRoot,
    };

    var result = await cd.ShowAsync();
        
    if ( result == ContentDialogResult.Primary )
    {
        aAction();
    }
}

ファイル選択ダイアログ

FileOpenPicker を使用して、ファイルを開く。

問題点として、初期ディレクトリに任意のフォルダを指定することができない。
ユーザー個々のドキュメントフォルダやピクチャフォルダなどを指定する必要がある。

上記で指定したルートフォルダのサブフォルダを指定することができないので
初回はユーザー自身が指定のフォルダへ移動する必要がある。

最後に選択した情報は保持され、次回開いた際にそのフォルダから開くことができる。

Bgmフォルダと譜面フォルダが分かれているので、ファイルの種類ごとに選択情報を保持したい場合は、
「FileOpenPicker.SettingsIdentifier」を指定する必要がある。

https://docs.microsoft.com/ja-JP/uwp/api/windows.storage.pickers.fileopenpicker.settingsidentifier?view=winrt-22621#windows-storage-pickers-fileopenpicker-settingsidentifier[FileOpenPicker.SettingsIdentifier]

public async static void OpenShowDialogAsync
( Window? aOwnerWindow, List<string> aFileTypeFilters, GeneralPath aOpenFilePath, PickerLocationId aInitialLocation, string aSettingsIdentifier )
{
	var picker = new FileOpenPicker
	{
	    // 表示モード:リスト
	    ViewMode = PickerViewMode.List,
	    // 初期ディレクトリ(初回のみ)
	    SuggestedStartLocation = aInitialLocation,
	    // ピッカー識別子(前回開いたフォルダ情報などを共有する際に使用)
	    SettingsIdentifier = aSettingsIdentifier,
	};

	// ファイルタイプのフィルタ設定
	aFileTypeFilters.ForEach( item => picker.FileTypeFilter.Add( item ) );

	if ( picker.FileTypeFilter.Count == 0 )
	{
	    picker.FileTypeFilter.Add( "*" );
	}

	// WinUI3 だと手間が増えてる・・・
	// https://docs.microsoft.com/ja-jp/windows/apps/windows-app-sdk/migrate-to-windows-app-sdk/guides/winui3
	// https://docs.microsoft.com/ja-JP/windows/apps/develop/ui-input/display-ui-objects

	InitializeWithWindow.Initialize( picker, WindowNative.GetWindowHandle( aOwnerWindow ) );

	// ファイル選択
	var file = await picker.PickSingleFileAsync();

	if ( file != null )
	{
            // 非同期処理が必要
	    //aOpenFilePath.AbsoulteFilePath = file.Path;
	}
}

色選択ダイアログ

Flyout

image

使い方あっているのかはわからない。flyoutの破棄処理は必要なのだろうか。

/// <summary>
/// 色選択ダイアログ(Flyout)
/// </summary>
/// <param name="aElement"></param>
/// <param name="aColor"></param>
/// <param name="aAction"></param>
public static void ColorDialog( FrameworkElement aElement, Color aColor, Action<Color> aAction )
{
    var stack_panel = new StackPanel()
    {
        Orientation = Orientation.Vertical,
        Spacing     = 6,
    };

    var color_picker = new ColorPicker
    {
        Color                           = aColor,
        ColorSpectrumComponents         = ColorSpectrumComponents.ValueSaturation,
        ColorSpectrumShape              = ColorSpectrumShape.Box,
        IsColorSpectrumVisible          = true,
        IsColorPreviewVisible           = true,
        IsMoreButtonVisible             = false,
        IsColorSliderVisible            = true,
        IsColorChannelTextInputVisible  = false,
        IsHexInputVisible               = true,
        IsAlphaEnabled                  = true,
        IsAlphaSliderVisible            = true,
        IsAlphaTextInputVisible         = false,
    };

    var apply_button = new Button()
    {
        Content = ResourcesHelper.GetString( "Dialog/Apply" ),
    };

    stack_panel.Children.Add( color_picker );
    stack_panel.Children.Add( apply_button );

    var flyout = new Flyout()
    {
        Content     = stack_panel,
        Placement   = FlyoutPlacementMode.Right,
    };

    // 適用ボタン押下時の処理
    apply_button.Click += ( sender, args ) => 
    { 
        aAction( color_picker.Color );

        flyout.Hide();
    };

    // Flyoutを追加し、表示する
    FlyoutBase.SetAttachedFlyout( aElement, flyout );
    FlyoutBase.ShowAttachedFlyout( aElement );
}

ContentDialog

image

ContentDialog で ColorPicker を表示すると Spectrum が表示されない
修正予定はあるのだろうか?
https://github.com/microsoft/microsoft-ui-xaml/issues/6474

対応としては、呼び出し元のページに ColorPickerを1個配置して それを呼び出すようにするのがいいのかな。
取り合えずはテキスト入力はできるので対応はしないが

public async static void ColorDialogAsync( XamlRoot aContentXamlRoot, Color aColor, Action<Color> aAction )
{
    var content = new ColorPicker
    {
        Color                           = aColor,
        ColorSpectrumComponents         = ColorSpectrumComponents.ValueSaturation,
        ColorSpectrumShape              = ColorSpectrumShape.Box,
        IsColorSpectrumVisible          = true,
        IsColorPreviewVisible           = true,
        IsMoreButtonVisible             = false,
        IsColorSliderVisible            = true,
        IsColorChannelTextInputVisible  = false,
        IsHexInputVisible               = true,
        IsAlphaEnabled                  = true,
        IsAlphaSliderVisible            = true,
        IsAlphaTextInputVisible         = false,
    };

    var cd = new ContentDialog
    {
        Title               = ResourcesHelper.GetString( "Dialog/Input" ),
        Content             = content,
        PrimaryButtonText   = ResourcesHelper.GetString( "Dialog/Ok" ),
        CloseButtonText     = ResourcesHelper.GetString( "Dialog/Cancel" ),
        XamlRoot            = aContentXamlRoot,
    };

    var result = await cd.ShowAsync();
        
    if ( result == ContentDialogResult.Primary )
    {
        aAction( content.Color );
    }
}
⚠️ **GitHub.com Fallback** ⚠️