?本文將介紹如何在.NET Core3環(huán)境下使用MVVM框架Prism的對話框服務,這也是prism系列的最后一篇完結(jié)文章,下面是Prism系列文章的索引:
.NET Core 3 WPF MVVM框架 Prism系列之文章索引
在Prism中,通過一個IDialogAware接口來實現(xiàn)對話框服務:
public interface IDialogAware{ bool CanCloseDialog(); void OnDialogClosed(); void OnDialogOpened(IDialogParameters parameters); string Title { get; set; } event Action<IDialogResult> RequestClose;}
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)); } //觸發(fā)窗體關(guān)閉事件 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"); } }
App.cs:
protected override void RegisterTypes(IContainerRegistry containerRegistry){ containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();}
還可以注冊時起名字:
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>(“alertDialog”);
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); }
效果如下:
我們是通過調(diào)用IDialogService接口的ShowDialog函數(shù)來調(diào)用,下面是該接口的定義:
public interface IDialogService : Object{ Void Show(String name, IDialogParameters parameters, Action<IDialogResult> callback); Void ShowDialog(String name, IDialogParameters parameters, Action<IDialogResult> callback); }
我們可以發(fā)現(xiàn)show和ShowDialog函數(shù)都是一樣形參,無非就是使用場景不一樣
?我們在上述可以看到,對話框的窗體時一個WPF自帶的窗體,但是當我們要用自己自定義窗體,例如,去掉window的Icon,保留最大化,最小化和關(guān)閉,或者使用一些第三方的窗體控件,prism支持通過注冊一個對話框窗體,然后通過再不同對話框的View指定其對話框窗體的style,則可以很靈活的實現(xiàn)不一樣的對話框,下面讓我們來看看如何操作:
新建一個窗體,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函數(shù)去除Window的Icon部分 } public IDialogResult Result { get; set; }}
App.cs:
protected override void RegisterTypes(IContainerRegistry containerRegistry){ containerRegistry.RegisterDialogWindow<DialogWindow>();//注冊自定義對話框窗體}
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>
那么就變成了下面這樣:
最終,我們的最后效果為這樣:
?通過Prism的對話框服務,我們可以很好的通過一個IDialogService接口來統(tǒng)一管理對話框的彈出邏輯,而且可以使用依賴注入的模式,如果換成之前要定義一些自定義的對話框,那么也要強依賴View部分,而且可以通過自定義不同對話框的窗體樣式,達到一定的靈活性(例如最終效果演示,用了兩個不同的對話框樣式),至此, .NET Core3.x Prism系列文章已經(jīng)全部寫完
?最后,附上整個demo的源代碼:PrismDemo源碼