Prims框架是WPF的一个框架,特点是集成了我们平常常用的开发模式,封装了很多常用的功能。例如消息通知,路由导航,Model绑定。
资料来源
WPF-Prism8.0核心教程(公益)
根据网上的说明,DryIoc是更加效率更高的,但是我看Nuget下载数量里面,Unity下载数量比DryIoc高得多。具体没怎么用过,那就按照推荐用DryIoc好了。
App.xaml.cs
///
/// 继承prism的PrismApplication类
///
public partial class App : PrismApplication
{
//设置启动页
protected override Window CreateShell()
{
//启动页为MainWindow
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
App.xaml
<prism:PrismApplication x:Class="PrismTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PrismTest"
xmlns:prism="http://prismlibrary.com/">
prism:PrismApplication>
xmlns:prism引入命名空间
prism:ViewModel设置自动绑定
可以不加,默认进行了绑定。
<Window ...
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
也可以在App.xaml里面强行绑定
在原文件件中取消绑定
app.xaml
/// <summary>
/// 路由管理
/// summary>
/// <param name="containerRegistry">param>
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//通过RegisterForNavigation进行强行绑定,强行让ViewA和ViewAViewModel进行绑定
containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
}
//继承BindableBase接口
public class MyListBoxItem : BindableBase
{
private string text;
public string Text
{
get { return text; }
set { SetProperty(ref text, value);}//此方法为Prism提供
}
}
可以输入propp加tab键,模板输入,提交写代码效率
函数动态绑定需要用到委托类型,如果委托不明白需要自己回去了解一下
viewModel
//声明委托
public DelegateCommand TestBtn { get; set; }
//构造函数
public MainWindowViewModel()
{
//实例化委托
TestBtn = new DelegateCommand(() =>
{
//执行内容
});
}
view
使用Command引用委托,如果没有TestBtn委托也不报错
<Button Content="测试方法"
FontSize="100"
Grid.Row="1"
Command="{Binding TestBtn}"/>
在扩展,管理扩展中安装
我们在新建程序的时候会有Prism模板框架
使用时会提示使用什么容器,这里推荐DryIoc容器
新建文件路径如下
Prism将界面继续划分,分为多个Region,在Region中添加元素。
和WPF用户组件的区别。
MainWindow.xaml
<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
Grid>
UserControl1.xaml,用于放置在Region上面的用户控件
<Grid>
<TextBlock Text="我是用户控件" FontSize="100"/>
Grid>
MainWindowViewModel.xaml
//注册regionManager控件
private readonly IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
//ContentRegion是窗口已声明的Region,使用字符串进行弱绑定
regionManager.RegisterViewWithRegion("ContentRegion",typeof(UserControl1));
}
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
Grid.ColumnDefinitions>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
Grid>
实现效果
消息订阅是先订阅再发布有效,如果是先发布再订阅则无效。
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
//声明委托
public DelegateCommand TestBtn { get; set; }
public DelegateCommand SendCommand { get; set; }
private readonly IEventAggregator _eventAggregator;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
//构造函数
public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator)
{
//实例化委托
//订阅
TestBtn = new DelegateCommand(() =>
{
eventAggregator.GetEvent<MessageEvent>().Subscribe(OnMessageRecevied);
});
//发送
SendCommand = new DelegateCommand(() =>
{
//执行参数
eventAggregator.GetEvent<MessageEvent>().Publish("Hello Event");
});
this._eventAggregator = eventAggregator;
}
public void OnMessageRecevied(string msg)
{
Title += msg + "\r\n";
}
//消息订阅类
public class MessageEvent: PubSubEvent<string> {
}
}
注意
eventAggregator.GetEvent
eventAggregator.GetEvent().
取消订阅
eventAggregator.GetEvent<MessageEvent>().Unsubscribe(OnMessageRecevied);
路由导航和Region是搭配使用的,专门用于页面转化
///
/// 路由管理
///
///
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//将ViewA,B,C添加到导航,这样才能进行路由管理
containerRegistry.RegisterForNavigation<ViewA>("ViewA");
containerRegistry.RegisterForNavigation<ViewB>();
containerRegistry.RegisterForNavigation<ViewC>();
}
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition />
Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="ViewA"
Command="{Binding OpenACommand}" />
<Button Content="ViewB"
Command="{Binding OpenBCommand}" />
<Button Content="ViewC"
Command="{Binding OpenC_Command}" />
<Button Content="上一页"
Command="{Binding GoBackCommand}" />
<Button Content="下一页"
Command="{Binding GoForwordCommand}"/>
StackPanel>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
Grid>
在MainiView里面管理导航
namespace PrismNavigation.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
///
/// 导航日志
///
private IRegionNavigationJournal _journal;
//Region,用于页面切换
private readonly IRegionManager _regionManager;
public DelegateCommand OpenACommand { get; set; }
public DelegateCommand OpenBCommand { get; set; }
public DelegateCommand OpenC_Command { get; set; }
public DelegateCommand GoBackCommand { get; set; }
public DelegateCommand GoForwordCommand { get; set; }
public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator)
{
_regionManager = regionManager;
OpenACommand = new DelegateCommand(OpenA);
OpenBCommand = new DelegateCommand(OpenB);
OpenC_Command = new DelegateCommand(OpenC);
GoBackCommand = new DelegateCommand(GoBack);
GoForwordCommand = new DelegateCommand(GoForword);
}
private void OpenA()
{
NavigationParameters para = new NavigationParameters
{
{ "Value", "Hello Prism" }
};
//进行路由传参,ContentRegion是xmal中的Region名称,ViewA是在App.xmal中注册的名称,arg是日志回调,para是路由传递的参数
_regionManager.RequestNavigate("ContentRegion", "ViewA", arg =>
{
///获取导航日志
_journal = arg.Context.NavigationService.Journal;
}, para);
}
private void OpenB()
{
_regionManager.RequestNavigate("ContentRegion", "ViewB", arg =>
{
///获取导航日志
_journal = arg.Context.NavigationService.Journal;
});
}
private void OpenC()
{
_regionManager.RequestNavigate("ContentRegion", "ViewC", arg =>
{
///获取导航日志
_journal = arg.Context.NavigationService.Journal;
});
}
private void GoForword()
{
_journal.GoForward();
}
private void GoBack()
{
_journal.GoBack();
}
}
}
在ViewA中进行路由拦截
public class ViewAViewModel :BindableBase, IConfirmNavigationRequest
{
private string _name;
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
///
/// IConfirmNavigationRequest的路由离开拦截,
///
///
///
///
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
var res = true;
if(MessageBox.Show("确认导航?","温馨提示",MessageBoxButton.YesNo) == MessageBoxResult.No)
{
res = false;
}
//如果res为true则拦截,true则放行
continuationCallback?.Invoke(res);
}
///
/// 用于判断是否要重新创建新的事例,即是否保留之前的信息,True为重新创建。
///
///
///
///
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
///
/// 离开页面时触发,一般用于取消事件监听
///
///
///
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
///
/// 显示页面前触发,一般用于设置事件监听
///
///
///
public void OnNavigatedTo(NavigationContext navigationContext)
{
//拿到Key为Value的值,返回类型为string
Name = navigationContext.Parameters.GetValue<string>("Value");
}
}
简单介绍
_regionManager.RequestNavigate("ContentRegion", "别名");//原本是ViewA的,可以替换成别名
Prism将对话框这个常用的功能进行了封装。虽然叫对话框,但其实是弹窗的功能效果。
app.xaml中
///
/// 路由管理
///
///
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
.......
//这里也能起别名
containerRegistry.RegisterDialog<MsgView,MsgViewModel>("别名");
}
MainViewModel使用这个弹窗
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
///
/// 导航日志
///
private IRegionNavigationJournal _journal;
private readonly IRegionManager _regionManager;
//注册弹窗服务
private IDialogService _dialogService;
public DelegateCommand OpenACommand { get; set; }
//构造函数中传入对话框
public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator,IDialogService dialogService)
{
_regionManager = regionManager;
OpenACommand = new DelegateCommand(OpenA);
GoForwordCommand = new DelegateCommand(GoForword);
//使用对话框
_dialogService = dialogService;
}
private void OpenA()
{
//对话框传递的参数
DialogParameters param = new DialogParameters();
param.Add("Value", "paramTest");
//打开名为MsgView的弹窗,并传递参数
_dialogService.Show("MsgView", param, arg =>
{
//弹窗关闭的回调函数,会有参数返回
if(arg.Result == ButtonResult.OK)
{
Debug.WriteLine("调试成功");
}
});
}
}
MsgView
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
<RowDefinition Height="50"/>
Grid.RowDefinitions>
<TextBox Grid.Row="1" Text="{Binding Title}" FontSize="20"/>
<Label Content="{Binding Title}"/>
<DockPanel Grid.Row="2" LastChildFill="False">
<Button Content="取消" Width="60"
DockPanel.Dock="Right"
Command="{Binding CancelCommand}" />
<Button Content="确定"
Width="60"
DockPanel.Dock="Right"
Command="{Binding SaveCommand}"/>
DockPanel>
Grid>
public class MsgViewModel :BindableBase, IDialogAware
{
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
///
/// 用于弹窗关闭的回调函数
///
public event Action<IDialogResult> RequestClose;
public DelegateCommand SaveCommand { get; set; }
public DelegateCommand CancelCommand { get; set; }
public MsgViewModel() {
SaveCommand = new DelegateCommand(() =>
{
DialogParameters keyValuePairs = new DialogParameters();
keyValuePairs.Add("Value", Title);
//执行弹窗关闭,并传入回调参数
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, keyValuePairs));
});
CancelCommand = new DelegateCommand(() =>
{
RequestClose?.Invoke(new DialogResult(ButtonResult.No));
});
}
///
/// 能否打开窗口
///
///
public bool CanCloseDialog()
{
return true;
}
///
/// 关闭的方法
///
///
public void OnDialogClosed()
{
//throw new NotImplementedException();
}
///
/// 打开之前,接受弹窗传参
///
///
///
public void OnDialogOpened(IDialogParameters parameters)
{
Title = parameters.GetValue<string>("Value");
}
}