?本文將介紹如何在.NET Core3環(huán)境下使用MVVM框架Prism的對(duì)話框服務(wù),這也是prism系列的最后一篇完結(jié)文章,下面是Prism系列文章的索引:
.NET Core 3 WPF MVVM框架 Prism系列之文章索引
一.對(duì)話框服務(wù)
在Prism中,,通過(guò)一個(gè)IDialogAware接口來(lái)實(shí)現(xiàn)對(duì)話框服務(wù):
public interface IDialogAware
{
bool CanCloseDialog();
void OnDialogClosed();
void OnDialogOpened(IDialogParameters parameters);
string Title { get; set; }
event Action<IDialogResult> RequestClose;
}
- CanCloseDialog()函數(shù)是決定窗體是否關(guān)閉
- OnDialogClosed()函數(shù)是窗體關(guān)閉時(shí)觸發(fā),,觸發(fā)條件取決于CanCloseDialog()函數(shù)
- OnDialogOpened()函數(shù)時(shí)窗體打開(kāi)時(shí)觸發(fā),比窗體Loaded事件早觸發(fā)
- Title為窗體的標(biāo)題
- RequestClose為關(guān)閉事件,,可由此控制窗體的關(guān)閉
1.創(chuàng)建對(duì)話框的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./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:///"
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");
}
}
2.注冊(cè)對(duì)話框
App.cs:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();
}
還可以注冊(cè)時(shí)起名字:
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>(“alertDialog”);
3.使用對(duì)話框服務(wù)
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={"是否需要用當(dāng)前注冊(cè)的用戶登錄?"}"), r =>
{
if (r.Result == ButtonResult.Yes)
navigationContext.Parameters.Add("loginId", RegisteredLoginId);
});
}
continuationCallback(true);
}
效果如下:
我們是通過(guò)調(diào)用IDialogService接口的ShowDialog函數(shù)來(lái)調(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ù)都是一樣形參,無(wú)非就是使用場(chǎng)景不一樣
- name:所要調(diào)用對(duì)話框view的名字,,當(dāng)注冊(cè)別名時(shí),,只能使用別名來(lái)調(diào)用
- parameters:IDialogParameters接口類型參數(shù),傳入的提示消息,通常是$"message={xxxx}"格式,,然后再ViewModel的OnDialogOpened函數(shù)通過(guò)IDialogParameters接口的GetValue函數(shù)來(lái)獲取
- callback:用于傳入無(wú)返回值回調(diào)函數(shù)
二.自定義對(duì)話框窗體
?我們?cè)谏鲜隹梢钥吹?,?duì)話框的窗體時(shí)一個(gè)WPF自帶的窗體,但是當(dāng)我們要用自己自定義窗體,,例如,,去掉window的Icon,保留最大化,,最小化和關(guān)閉,,或者使用一些第三方的窗體控件,prism支持通過(guò)注冊(cè)一個(gè)對(duì)話框窗體,,然后通過(guò)再不同對(duì)話框的View指定其對(duì)話框窗體的style,,則可以很靈活的實(shí)現(xiàn)不一樣的對(duì)話框,下面讓我們來(lái)看看如何操作:
1.注冊(cè)自定義對(duì)話框窗體
新建一個(gè)窗體,,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./markup-compatibility/2006"
xmlns:local="clr-namespace:PrismMetroSample.Shell.Views.Dialogs"
mc:Ignorable="d"
xmlns:prism="http:///"
>
<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>();//注冊(cè)自定義對(duì)話框窗體
}
2.自定義對(duì)話框窗體Style
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>
效果如下:
如何我們要將窗體樣式全部去掉,,改動(dòng)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>
那么就變成了下面這樣:
最終,我們的最后效果為這樣:
三.小結(jié)
?通過(guò)Prism的對(duì)話框服務(wù),,我們可以很好的通過(guò)一個(gè)IDialogService接口來(lái)統(tǒng)一管理對(duì)話框的彈出邏輯,,而且可以使用依賴注入的模式,如果換成之前要定義一些自定義的對(duì)話框,,那么也要強(qiáng)依賴View部分,,而且可以通過(guò)自定義不同對(duì)話框的窗體樣式,達(dá)到一定的靈活性(例如最終效果演示,,用了兩個(gè)不同的對(duì)話框樣式),,至此, .NET Core3.x Prism系列文章已經(jīng)全部寫(xiě)完
四.源碼
?最后,附上整個(gè)demo的源代碼:PrismDemo源碼
|