WPF Prism 入门 1

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.需要保证命名规范的正确性

  1. View可以以View结尾,也可以不写。
  2. 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,属性的绑定和通知,命令的绑定,消息的传递就介绍完了。

 

posted @ 2022-08-24 22:18  薛定谔的小灯泡  阅读(3675)  评论(2编辑  收藏  举报