本文は転載です。
原著者:RyzenAdorer
原題:.NET Core 3 WPF MVVM フレームワーク Prism シリーズのダイアログサービス
原文リンク:https://www.cnblogs.com/ryzen/p/12771986.html
本記事では、.NET Core3 環境で MVVM フレームワーク Prism のダイアログサービスを使用する方法を紹介します。これは prism シリーズ最後の完結記事です。以下は Prism シリーズの記事の索引です:
.NET Core 3 WPF MVVM フレームワーク Prism シリーズの記事索引
1. ダイアログサービス
Prism では、IDialogAware インターフェースを介してダイアログサービスを実装します:
public interface IDialogAware
{
bool CanCloseDialog();
void OnDialogClosed();
void OnDialogOpened(IDialogParameters parameters);
string Title { get; set; }
event Action<IDialogResult> RequestClose;
}
CanCloseDialog()関数は、ウィンドウを閉じるかどうかを決定します。OnDialogClosed()関数は、ウィンドウが閉じられたときにトリガーされます。トリガー条件はCanCloseDialog()関数に依存します。OnDialogOpened()関数は、ウィンドウが開かれたときにトリガーされます。これはウィンドウのLoadedイベントよりも前に発生します。Titleはウィンドウのタイトルです。RequestCloseはクローズイベントで、これによってウィンドウのクローズを制御できます。
2.1. ダイアログの View と ViewModel を作成する
AlertDialog.xaml:
<UserControl
x:Class="PrismMetroSample.Shell.Views.Dialogs.AlertDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PrismMetroSample.Shell.Views.Dialogs"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Width="350"
Height="120"
prism:ViewModelLocator.AutoWireViewModel="True"
>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<image
Source="pack://application:,,,/PrismMetroSample.Infrastructure;Component/Assets/Photos/alter.png"
Height="40"
UseLayoutRounding="True"
RenderOptions.BitmapScalingMode="HighQuality"
/>
<TextBlock
Grid.Column="1"
Text="{Binding Message}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Grid.Row="0"
TextWrapping="Wrap"
FontSize="15"
FontFamily="Open Sans"
/>
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<button
Margin="5"
Foreground="White"
FontSize="12"
Background="#5cb85c"
Command="{Binding CloseDialogCommand}"
CommandParameter="true"
Content="Yes"
Width="64"
Height="28"
HorizontalAlignment="Right"
Grid.Row="1"
/>
<button
Grid.Column="1"
Margin="5"
Foreground="White"
FontSize="12"
Background="#d9534f"
Command="{Binding CloseDialogCommand}"
CommandParameter="false"
Content="No"
Width="64"
Height="28"
HorizontalAlignment="Left"
Grid.Row="1"
/>
</Grid>
</Grid>
</UserControl>
AlertDialogViewModel.cs:
public class AlertDialogViewModel : BindableBase, IDialogAware
{
private DelegateCommand<string> _closeDialogCommand;
public DelegateCommand<string> CloseDialogCommand =>
_closeDialogCommand ?? (_closeDialogCommand = new DelegateCommand<string>(ExecuteCloseDialogCommand));
void ExecuteCloseDialogCommand(string parameter)
{
ButtonResult result = ButtonResult.None;
if (parameter?.ToLower() == "true")
result = ButtonResult.Yes;
else if (parameter?.ToLower() == "false")
result = ButtonResult.No;
RaiseRequestClose(new DialogResult(result));
}
// ウィンドウクローズイベントをトリガーする
public virtual void RaiseRequestClose(IDialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
private string _message;
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
private string _title = "Notification";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
Message = parameters.GetValue<string>("message");
}
}
2.2. ダイアログを登録する
App.cs:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();
}
また、登録時に名前を付けることもできます:
Copy
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>("alertDialog");
2.3. ダイアログサービスを使用する
CreateAccountViewModel.cs(変更部分):
public CreateAccountViewModel(IRegionManager regionManager, IDialogService dialogService)
{
_regionManager = regionManager;
_dialogService = dialogService;
}
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
if (!string.IsNullOrEmpty(RegisteredLoginId) && this.IsUseRequest)
{
_dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"現在登録しているユーザーでログインしますか?"}"), r =>
{
if (r.Result == ButtonResult.Yes)
navigationContext.Parameters.Add("loginId", RegisteredLoginId);
});
}
continuationCallback(true);
}
効果は次のとおりです:

IDialogService インターフェースの ShowDialog 関数を呼び出して使用します。以下はそのインターフェースの定義です:
public interface IDialogService : Object
{
Void Show(String name, IDialogParameters parameters, Action<IDialogResult> callback);
Void ShowDialog(String name, IDialogParameters parameters, Action<IDialogResult> callback);
}
Show と ShowDialog 関数の引数は同じで、使用シナリオが異なるだけです。
name:呼び出すダイアログ View の名前。エイリアスを登録した場合は、エイリアスのみを使用して呼び出す必要があります。parameters:IDialogParametersインターフェース型のパラメータで、渡すメッセージです。通常は$"message={xxxx}"の形式で、ViewModel のOnDialogOpened関数でIDialogParametersインターフェースのGetValue関数を使用して取得します。callback:戻り値のないコールバック関数を渡すために使用します。
2. カスタムダイアログウィンドウ
上記では、ダイアログのウィンドウは WPF 標準のウィンドウですが、カスタムウィンドウ(Window のアイコンを削除する、最大化・最小化・閉じるを保持する、またはサードパーティのウィンドウコントロールを使用するなど)を使用したい場合、Prism はダイアログウィンドウを登録し、異なるダイアログの View にそのダイアログウィンドウのスタイルを指定することで、柔軟に異なるダイアログを実装できます。以下にその方法を示します。
2.1. カスタムダイアログウィンドウを登録する
新しいウィンドウを作成します:DialogWindow.xaml
<Window
x:Class="PrismMetroSample.Shell.Views.Dialogs.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PrismMetroSample.Shell.Views.Dialogs"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
>
<Grid> </Grid>
</Window>
DialogWindow.xaml.cs:
public partial class DialogWindow : Window, IDialogWindow
{
public DialogWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
WindowHelp.RemoveIcon(this); // win32 関数を使用して Window のアイコン部分を削除
}
public IDialogResult Result { get; set; }
}
App.cs:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialogWindow<DialogWindow>(); // カスタムダイアログウィンドウを登録
}
2.2. カスタムダイアログウィンドウのスタイル
AlertDialog.xaml:
<prism:Dialog.WindowStyle>
<style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="SizeToContent" Value="WidthAndHeight"/>
</style>
</prism:Dialog.WindowStyle>
効果は次のとおりです:

ウィンドウスタイルを完全に削除するには、AlertDialog.xaml を変更します:
<prism:Dialog.WindowStyle>
<style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="SizeToContent" Value="WidthAndHeight"/>
<Setter Property="WindowStyle" Value="None"/>
</style>
</prism:Dialog.WindowStyle>
すると、次のようになります:

最終的な効果は次のとおりです:

3. まとめ
Prism のダイアログサービスを使用すると、IDialogService インターフェースを介してダイアログの表示ロジックを一元管理でき、依存性注入パターンを使用できます。以前のようにカスタムダイアログを定義する場合、View 部分に強く依存していましたが、Prism では異なるダイアログのウィンドウスタイルをカスタマイズすることで、柔軟性を高めることができます(最終的な効果のデモでは、2 つの異なるダイアログスタイルを使用しています)。以上で、.NET Core3.x Prism シリーズの記事はすべて完了です。
4. ソースコード
最後に、デモのソースコード全体を添付します:PrismDemo ソースコード