电竞比分网-中国电竞赛事及体育赛事平台

分享

.NET Core 3 WPF MVVM框架 Prism系列之對話框服務(wù)

 丹楓無跡 2021-04-02

?本文將介紹如何在.NET Core3環(huán)境下使用MVVM框架Prism的對話框服務(wù),這也是prism系列的最后一篇完結(jié)文章,下面是Prism系列文章的索引:
.NET Core 3 WPF MVVM框架 Prism系列之文章索引

一.對話框服務(wù)

在Prism中,通過一個IDialogAware接口來實現(xiàn)對話框服務(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)閉時觸發(fā),觸發(fā)條件取決于CanCloseDialog()函數(shù)
  • OnDialogOpened()函數(shù)時窗體打開時觸發(fā),比窗體Loaded事件早觸發(fā)
  • Title為窗體的標(biāo)題
  • RequestClose為關(guān)閉事件,可由此控制窗體的關(guān)閉

1.創(chuàng)建對話框的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.注冊對話框

App.cs:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();
}

還可以注冊時起名字:

containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>(“alertDialog”);

3.使用對話框服務(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)前注冊的用戶登錄?"}"), 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ù)都是一樣形參,無非就是使用場景不一樣

  • name:所要調(diào)用對話框view的名字,當(dāng)注冊別名時,只能使用別名來調(diào)用
  • parameters:IDialogParameters接口類型參數(shù),傳入的提示消息,通常是$"message={xxxx}"格式,然后再ViewModel的OnDialogOpened函數(shù)通過IDialogParameters接口的GetValue函數(shù)來獲取
  • callback:用于傳入無返回值回調(diào)函數(shù)

二.自定義對話框窗體

?我們在上述可以看到,對話框的窗體時一個WPF自帶的窗體,但是當(dāng)我們要用自己自定義窗體,例如,去掉window的Icon,保留最大化,最小化和關(guān)閉,或者使用一些第三方的窗體控件,prism支持通過注冊一個對話框窗體,然后通過再不同對話框的View指定其對話框窗體的style,則可以很靈活的實現(xiàn)不一樣的對話框,下面讓我們來看看如何操作:

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./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>();//注冊自定義對話框窗體
}

2.自定義對話框窗體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>

效果如下:

如何我們要將窗體樣式全部去掉,改動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é)

?通過Prism的對話框服務(wù),我們可以很好的通過一個IDialogService接口來統(tǒng)一管理對話框的彈出邏輯,而且可以使用依賴注入的模式,如果換成之前要定義一些自定義的對話框,那么也要強依賴View部分,而且可以通過自定義不同對話框的窗體樣式,達(dá)到一定的靈活性(例如最終效果演示,用了兩個不同的對話框樣式),至此, .NET Core3.x Prism系列文章已經(jīng)全部寫完

四.源碼

?最后,附上整個demo的源代碼:PrismDemo源碼

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多