1.Region(区域管理)
在最常见的开发模式当中, 我们去设计某个页面的时候, 实际上界面元素在设计的时候已经被固定。
举个简单的例子,当我们去设计如下页面, 它包含Header、Menu、Content内容。
1.1定义Region
可以使用XAML或代码创建定义Region
XAML:
<Window
x:Class="HT.PrismApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Width="525"
Height="350"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" prism:RegionManager.RegionName="HeaderRegion" />
<Grid Grid.Row="1" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0" prism:RegionManager.RegionName="MenuRegion" />
<ContentControl Grid.Column="1" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Grid>
</Window>
C#定义:RegionManager.SetRegionName("控件名","区域名称");
1.2注册区域视图
using HT.PrismApp.Views;
using Prism.Mvvm;
using Prism.Regions;
namespace HT.PrismApp.ViewModels
{
public class MainWindowViewModel : BindableBase
{
public MainWindowViewModel(IRegionManager regionManager)
{
regionManager.RegisterViewWithRegion("HeaderRegion",typeof(HeaderView));
regionManager.RegisterViewWithRegion("MenuRegion", typeof(MenuView));
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ContentView));
}
}
}
2.ViewModelLocator
在WPF当中,需要为View与ViewModel建立连接, 我们需要找到View的DataContext, 如下所示:
XAML的方式:
<UserControl.DataContext>
<.../>
</UserControl.DataContext>
代码的方式:
public partial class ViewA : UserControl
{
public ViewA()
{
InitializeComponent();
this.DataContext = null; //设定
}
}
在Prism当中, 你可以基于命名约定, 便能够轻松的将View/ViewModel建议关联。如下所示:
假设你已经为项目添加Views和ViewModels文件夹。此时, 你的页面为ViewA, 则对应的ViewModel名称为 ViewAViewModel。
错误命名例子:假如你的页面为PageView,对应的ViewModel名称为PageViewModel,而不是PageViewViewModel。
3.MVVM
众所周知, 如果你了解WPF当中的ICommand, INotifyPropertyChanged的作用, 就会发现
众多框架都是基于这些进行扩展, 实现其通知、绑定、命令等功能。
3.1通知
Prism继承Prism.Mvvm.BindableBase,进行调用RaisePropertyChanged方法即可。
3.2命令
Prism继承Prism.Mvvm.BindableBase,进行使用DelegateCommand即可。
3.3拓展
对于单个Command而言, 只是触发单个对应的功能, 而复合命令是Prism当中非常强大的功能, CompositeCommand简单来说是一个父命令, 它可以注册N个子命令。
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace HT.PrismApp.ViewModels
{
public class ContentViewModel : BindableBase
{
public ContentViewModel()
{
ACommamd = new DelegateCommand(() =>
{
Title += "ACommamd";
});
BCommamd = new DelegateCommand(() =>
{
Title += "BCommamd";
});
//复合命令
ClickAllCommand = new CompositeCommand();
ClickAllCommand.RegisterCommand(ACommamd);
ClickAllCommand.RegisterCommand(BCommamd);
}
private string title="测试";
public string Title
{
get
{
return title;
}
set
{
title = value;
RaisePropertyChanged(nameof(Title));
}
}
public DelegateCommand ACommamd;
public DelegateCommand BCommamd;
public DelegateCommand SaveCommamd
{
get
{
return new DelegateCommand(() =>
{
});
}
}
public CompositeCommand ClickAllCommand { get; set; }
}
}
3.4IEventAggregator(事件通讯)
发布:
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace HT.PrismApp.ViewModels
{
public class ContentViewModel : BindableBase
{
private readonly IEventAggregator _eventAggregator;
public ContentViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
private string msg;
public string Msg
{
get
{
return msg;
}
set
{
msg = value;
RaisePropertyChanged(nameof(Msg));
}
}
public DelegateCommand SendCommamd
{
get
{
return new DelegateCommand(() =>
{
_eventAggregator.GetEvent<PubSubEvent<string>>().Publish(Msg);
});
}
}
}
}
订阅:
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HT.PrismApp.ViewModels
{
public class HeaderViewModel : BindableBase
{
public HeaderViewModel(IEventAggregator eventAggregator)
{
eventAggregator.GetEvent<PubSubEvent<string>>().Subscribe(ReceiveMessage, ThreadOption.PublisherThread, false, msg =>
{
//过滤
return true;
});
}
private void ReceiveMessage(string msg)
{
Text = msg;
}
private string text;
public string Text
{
get
{
return text;
}
set
{
text = value;
RaisePropertyChanged(nameof(Text));
}
}
}
}
4.Navigation(导航)
4.1导航的基本条件:注册显示区域、注册导航页面
(1)注册导航
using HT.PrismApp.ViewModels;
using HT.PrismApp.Views;
using Prism.Ioc;
using System.Windows;
namespace HT.PrismApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//注册导航
containerRegistry.RegisterForNavigation<ContentView>();
containerRegistry.RegisterForNavigation<MenuView>();
//指定VieModel
//containerRegistry.RegisterForNavigation<ContentView, ContentViewModel>();
//containerRegistry.RegisterForNavigation<MenuView, MenuViewModel>();
}
}
}
2.使用导航
using HT.PrismApp.Views;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace HT.PrismApp.ViewModels
{
public class HeaderViewModel : BindableBase
{
private IRegionManager _regionManager;
public HeaderViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public DelegateCommand NavigationA
{
get
{
return new DelegateCommand(() =>
{
//使用导航
_regionManager.RequestNavigate("ContentRegion", nameof(ContentView));
});
}
}
public DelegateCommand NavigationB
{
get
{
return new DelegateCommand(() =>
{
//使用导航
_regionManager.RequestNavigate("ContentRegion", nameof(MenuView));
});
}
}
}
}
拓展:
public DelegateCommand NavigationA
{
get
{
return new DelegateCommand(() =>
{
//带参数,ViewModel继承INavigationAware
//OnNavigatedTo: 导航完成前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
//IsNavigationTarget: 调用以确定此实例是否可以处理导航请求。否则新建实例
//OnNavigatedFrom: 当导航离开当前页时, 类似打开A, 再打开B时, 该方法被触发。
//还有可以继承IConfirmNavigationRequest
//拦截导航请求
//public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
//{
// bool result = true;
// if (MessageBox.Show("确认导航?", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.No)
// result = false;
// //通过回调当前返回的确认结果,决定是否启动该导航
// continuationCallback(result);
//}
var param = new NavigationParameters();
param.Add("Parameter", param);
_regionManager.RequestNavigate("ContentRegion", nameof(ContentView), param);
//类似URL地址传递参数
//_regionManger.RequestNavigate("ContentRegion", $"{nameof(ContentView)}?id=1&Name=xiaoming");
});
}
}
3.Navigation Journal导航日志
using HT.PrismApp.Views;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace HT.PrismApp.ViewModels
{
public class HeaderViewModel : BindableBase
{
private IRegionManager _regionManager;
private IRegionNavigationJournal _journal;
public HeaderViewModel(IRegionManager regionManager, IRegionNavigationJournal journal)
{
_regionManager = regionManager;
_journal = journal;
}
public DelegateCommand NavigationA
{
get
{
return new DelegateCommand(() =>
{
_regionManager.RequestNavigate("ContentRegion", nameof(ContentView), args =>
{
//***导航日志
_journal = args.Context.NavigationService.Journal;
});
});
}
}
public DelegateCommand NavigationB
{
get
{
return new DelegateCommand(() =>
{
//使用导航
_regionManager.RequestNavigate("ContentRegion", nameof(MenuView), args =>
{
//***导航日志
_journal = args.Context.NavigationService.Journal;
});
});
}
}
public DelegateCommand GoBack
{
get
{
return new DelegateCommand(() =>
{
_journal.GoBack();
});
}
}
public DelegateCommand GoForward
{
get
{
return new DelegateCommand(() =>
{
_journal.GoForward();
});
}
}
}
}
5.Dialog(对话框)
对话框实际上是我们应用程序经常用到的一个功能, 类如: Show、ShowDialog。
可以弹出一个我们指定的窗口, 仅此而已, 那么在Prism当中, Dialog指的是什么?
Prism提供了一组对话服务, 封装了常用的对话框组件的功能, 例如:
- RegisterDialog/IDialogService (注册对话及使用对话)
- 打开对话框传递参数/关闭对话框返回参数
- 回调通知对话结果
5.1创建对话框,通常是一组用户控件 ,并且实现 IDialogAware
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
namespace HT.PrismApp.ViewModels
{
public class MessageDialogViewModel : BindableBase, IDialogAware
{
public string Title => "对话框服务";
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
/// <summary>
/// 对话框关闭时
/// </summary>
public void OnDialogClosed()
{
}
/// <summary>
/// 对话框打开时
/// </summary>
/// <param name="parameters"></param>
public void OnDialogOpened(IDialogParameters parameters)
{
}
public DelegateCommand SaveCommand
{
get
{
return new DelegateCommand(() =>
{
RequestClose?.Invoke(new DialogResult(ButtonResult.OK));
});
}
}
public DelegateCommand CancelCommand
{
get
{
return new DelegateCommand(() =>
{
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
});
}
}
}
}
5.2注册对话框 RegisterDialog
using HT.PrismApp.ViewModels;
using HT.PrismApp.Views;
using Prism.Ioc;
using System.Windows;
namespace HT.PrismApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<MessageDialog, MessageDialogViewModel>();
}
}
}
5.3使用IDialogService接口 Show/ShowDialog 方法调用对话框
using HT.PrismApp.Views;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace HT.PrismApp.ViewModels
{
public class HeaderViewModel : BindableBase
{
private IRegionManager _regionManager;
private IRegionNavigationJournal _journal;
private IDialogService _dialogService;
public HeaderViewModel(IRegionManager regionManager, IRegionNavigationJournal journal, IDialogService dialogService)
{
_regionManager = regionManager;
_journal = journal;
_dialogService= dialogService;
}
public DelegateCommand NavigationA
{
get
{
return new DelegateCommand(() =>
{
_regionManager.RequestNavigate("ContentRegion", nameof(ContentView), args =>
{
//***导航日志
_journal = args.Context.NavigationService.Journal;
});
});
}
}
public DelegateCommand NavigationB
{
get
{
return new DelegateCommand(() =>
{
//使用导航
_regionManager.RequestNavigate("ContentRegion", nameof(MenuView), args =>
{
//***导航日志
_journal = args.Context.NavigationService.Journal;
});
});
}
}
public DelegateCommand GoBack
{
get
{
return new DelegateCommand(() =>
{
_journal.GoBack();
});
}
}
public DelegateCommand GoForward
{
get
{
return new DelegateCommand(() =>
{
_journal.GoForward();
});
}
}
public DelegateCommand OpenDialog
{
get
{
return new DelegateCommand(() =>
{
_dialogService.ShowDialog(nameof(MessageDialog));
});
}
}
}
}