1.新建prsim工程,修改工程
新建wpf工程,Nuget添加prism.Unity,自动添加需要的包
项目结构:
修改App.xaml
修改前:
修改后:
App.xaml.cs:
到这一步,一个wpf基于prism的工程就可以运行了,修改一下项目结构,用于自动绑定ViewModel
把MainWindow放到Views下,需要修改3个地方
Mainwindow.xaml:命名空间
x:Class="Demo.Views.MainWindow"
Mainwindow.xaml.cs命名空间
namespace Demo.Views
app.xaml.cs中命名空间(需要实现接口CreateShell()和RegisterTypes)
return Container.Resolve<Views.MainWindow>();
prism工程默认把界面放在Views目录下,把对应的View Model、
放在ViewModel目录下
2.View和ViewModel的绑定
prism会自动完成View和ViewModel的绑定,前提条件是:
1.View中引入名称空间:xmlns:prism="http://prismlibrary.com/"
2.设置为自动关联:prism:ViewModelLocator.AutoWireViewModel="True"
3.必须是Views和ViewModels目录,目录的名字不能变
4.需要保证命名规范的正确性
- View可以以View结尾,也可以不写。
- ViewModel必须以View的名称+”ViewModel”进行命名
这些是默认的规则,也可以通过App.cs 中重写ConfigureViewModelLocator方法自定义规则
代码:在App.xaml.cs中
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), typeof(TestVM));
}
在默认规则下,Views下的MianWindow会自动绑定MainWindowViewModel,通过修改规则,让他绑定到TestVM上
两个类的代码:
运行结果:
3.属性的绑定和通知
在Prism框架下要完成属性的绑定和自动通知,只需要做2步即可
1.在属性所在的类继承BindableBase基类
2.在属性的set访问器中添加SetProperty(ref xxx, value)
public class MainWindowViewModel : BindableBase
{
private string str;
public string Str
{
get { return str; }
set { SetProperty(ref str, value); }
}
public MainWindowViewModel()
{
Str = "Binding";
}
}
}
在SetProperty中加了数据的判断,只有数据真正有变化时才会执行RaisePropertyCHanged,如果数据和之前的数据相同,则不执行。这样做提高了程序的效率
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value))
{
return false;
}
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
4.命令的绑定
使用快捷键输入,输入按2此Tab。总共有4个
cmd 不带参数和CanEexecute方法的命令
private DelegateCommand _fieldName;
public DelegateCommand CommandName =>
_fieldName ?? (_fieldName = new DelegateCommand(ExecuteCommandName));
void ExecuteCommandName()
{
}
cmdgfull 带参数和CanExecute方法的命令
private DelegateCommand<string> _fieldName;
public DelegateCommand<string> CommandName =>
_fieldName ?? (_fieldName = new DelegateCommand<string>(ExecuteCommandName, CanExecuteCommandName));
void ExecuteCommandName(string parameter)
{
}
bool CanExecuteCommandName(string parameter)
{
return true;
}
cmdfull 不带参数,带Canexecute方法的命令
private DelegateCommand _fieldName;
public DelegateCommand CommandName =>
_fieldName ?? (_fieldName = new DelegateCommand(ExecuteCommandName, CanExecuteCommandName));
void ExecuteCommandName()
{
}
bool CanExecuteCommandName()
{
return true;
}
cmdg 带参数不带Canexecute方法的命令
private DelegateCommand<string> _fieldName;
public DelegateCommand<string> CommandName =>
_fieldName ?? (_fieldName = new DelegateCommand<string>(ExecuteCommandName));
void ExecuteCommandName(string parameter)
{
}
命令都是固定格式的,只需要修改命令的名字,参数的类型,传入委托即可。
一个命令的固定格式分析,在写自己的命令时,自己决定是不是要传参数,要不要CanExecute方法
运行结果:
点击按钮前:
点击按钮后:
5.InvokeCommandAction任意事件的绑定
和mvvmlight,mvvmtoolkit一样,只有少数控件有Command参数,下面接受在Prism框架下,任意事件的绑定(为什么绑定命令?可以简单理解,实现界面和数据分离,可以在ViewModel中写命令的处理逻辑)
第一步:在View中添加命名空间
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
第二步:给Combox的SelectionChanged添加命令
<ComboBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<prism:InvokeCommandAction Command="{Binding ComboxSelectedChanged}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBoxItem Content="111"/>
<ComboBoxItem Content="222"/>
<ComboBoxItem Content="333"/>
</ComboBox>
ViewModel中:
private DelegateCommand<object> comboxSelectedChanged;
public DelegateCommand<object> ComboxSelectedChanged =>
comboxSelectedChanged ?? (comboxSelectedChanged = new DelegateCommand<object>(ExecuteComboxSelectedChanged));
void ExecuteComboxSelectedChanged(object parameter)
{
}
需要注意的时命令的参数要写Object类型,按照这个步骤,可以给任意的控件的任意事件绑定到命令,默认是传递EventArgs
6.事件聚合器,订阅 发布
Prism框架下,View和ViewModel之间互相传递消息
1.定义一个基本消息类型MessageEvent,继承PubSubEvent
这个MessageEvenet继承PubSubEvent,<>括号内写消息的类型,
例子1:View和ViewModel之间传递消息
View:
public partial class MainWindow : Window
{
public MainWindow( IEventAggregator eventAggregator)
{
InitializeComponent();
eventAggregator.GetEvent<MessageEvent>().Subscribe(On);
}
private void On(object obj)
{
}
}
ViewModel:
构造函数注入TEventAggregator
public IEventAggregator MyEventAggregator;
public MainWindowViewModel( IEventAggregator eventAggregator)
{
// Str = "Binding";
MyEventAggregator = eventAggregator;
}
当什么时候,发送这个消息,(当Combox发生SelectionCHanged事件后发送消息,这是我随便找的,具体在哪里发送,看自己的需求)
private DelegateCommand<object> comboxSelectedChanged;
public DelegateCommand<object> ComboxSelectedChanged =>
comboxSelectedChanged ?? (comboxSelectedChanged = new DelegateCommand<object>(ExecuteComboxSelectedChanged));
void ExecuteComboxSelectedChanged(object parameter)
{
MyEventAggregator.GetEvent<MessageEvent>().Publish(parameter);
}
需要注意的几点:
1.Prism框架下,在同一程序中获取 IEventAggregator ,都是同一个对象,这个是由IOC容器提供的功能,
2.发布消息 和订阅消息的双发需要根据消息的类型判断是否匹配
3.在需要的使用IEventAggregator的View或者ViewModel中,在该类的构造函数中注入IEventAggregator
4.View ViewModel之间可以互相定于和发布。 即使不在同一个程序集也可以。(使用Prism的Module的情况下,需要把消息类型写在公共程序集中)
至此,Prism的基本功能包括 新建工程,初始化app,属性的绑定和通知,命令的绑定,消息的传递就介绍完了。