WPF之prism的基本使用

WPF之prism的基本使用

项目创建

先创建一个wpf项目,再引入包,可以直接引入Prism.Unity包,这个包会包含基础的包,并使用Unity的容器管理
在这里插入图片描述

在App.xaml中修改为prismApp并去掉starturi

<prism:PrismApplication
    x:Class="wpf.prism.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:wpf.prism"
    xmlns:prism="http://prismlibrary.com/">
    <Application.Resources />
</prism:PrismApplication>

在App.xaml.cs中实现PrismApplication接口,该接口包含CreateShell和RegisterTypes两个方法需要实现。

CreateShell是返回打开的主窗口,一般通过容器获取。

RegisterTypes是用于注册需要的各种类,包括view和viewModel。

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterInstance<MyService>(new MyService());
        containerRegistry.RegisterSingleton<MainViewModel>();
        containerRegistry.RegisterDialog<LoginDialog, LoginDialogViewModel>("loginDialog");
        containerRegistry.RegisterSingleton<ViewAViewModel>();
        containerRegistry.RegisterForNavigation<ViewA>();
    }
}

1.mvvm

该框架的mvvm相关功能模块主要在Prism.Core这个包中,该包实现了一有关INotifyPropertyChanged和ICommand的相关功能。

1.1.通知

通过实现BindableBase接口来实现对界面的通知功能。需要写完整的字段和属性,并调用SetProperty方法来通知.

还有RaisePropertyChanged方法也可以实现通知效果,但是因为没有值校验,会导致所有的数据都会通知前台,不建议使用。

public class MainViewModel : BindableBase
{
    //这样定义一个可以通知view的属性
    private string? _showText = "this is original value";

    public string? ShowText
    {
        get { return _showText; }
        set { SetProperty(ref _showText, value); }
    }
}

页面绑定到这个属性,这样后台的值发生变化时,前台页面也会修改

<Grid>
    <TextBox Text="{Binding ShowText}" />
</Grid>

1.2.命令(Command)

使用此工具包可以快捷创建一个新的命令,实例化时,可以传入两个参数,分别为触发执行函数,判断是否可执行的函数。

可以安装prism的扩展,然后就可以输入cmd快捷生成这一段代码

 private DelegateCommand _updateCommand;

 public DelegateCommand UpdateCommand =>
     _updateCommand ?? (_updateCommand = new DelegateCommand(ExecuteCommandName, canExecuteMethod: CanUpdated));

 //是否可以执行,比如当ShowText属性不为空时才可以执行
 bool CanUpdated() => !string.IsNullOrEmpty(ShowText);

 //执行的命令
 void ExecuteCommandName()
 {
	//do sth.
 }

使用ObservableProperty方法可以根据传入的属性变化从而执行CanExecute方法更新

//这样定义一个可以通知view的属性
private string? _showText = "this is original value";

public string? ShowText
{
    get { return _showText; }
    set { SetProperty(ref _showText, value); }
}

private DelegateCommand _updateCommand;

 public DelegateCommand UpdateCommand =>
     _updateCommand ?? (_updateCommand = new DelegateCommand(ExecuteCommandName, canExecuteMethod: CanUpdated).ObservesProperty(() => ShowText));

 //执行的命令
 void ExecuteCommandName()
 {
	//...
 }

另外,是否可执行可以与前台页面相互联动,比如当命令不能执行时,按钮为灰色。

为实现这个效果,可以让button的IsEnabled方法绑定一个属性,在执行canExeCute方法时更新ui

private bool _isEnabled;
//这个属性绑定到Button的isEnabled
public bool IsEnabled
{
    get { return _isEnabled; }
    set { SetProperty(ref _isEnabled, value); }
}

public DelegateCommand UpdateCommand =>
    _updateCommand ?? (_updateCommand = new DelegateCommand(ExecuteCommandName, canExecuteMethod: CanUpdated).ObservesProperty(() => ShowText));

//是否可以执行
bool CanUpdated()
{
    var able = !string.IsNullOrEmpty(ShowText); 
	执行时更改这个属性
    IsEnabled = able;
    return able;
}

1.3.viewModel间的通信

prism使用注册和订阅来进行viewModel之间的通信,首先需要通过实现Pub接口定义一个订阅类,规定传递的数据类型

//创建一个订阅类,根据泛型传递string类型的数据,订阅双方使用这个类来传递数据
public class MyMessager : PubSubEvent<string>
{

}

然后再实例在需要通信的两个类中引入订阅类,通常是使用依赖注入的方式。

//发送方
public class MainViewModel : BindableBase
{
	public MainViewModel(IEventAggregator ea)
	{
    	this.ea = ea;
	}

	void SendMsg()
	{
		//发送消息
		ea.GetEvent<MyMessager>().Publish("send a msg");
	}
}

//接收方
public class SonViewModel : BindableBase
{
    private string? _reveivedMsg;

    private readonly IEventAggregator ea;

    public string? ReceivedMsg
    {
        get { return _reveivedMsg; }
        set { SetProperty(ref _reveivedMsg, value); }
    }

    public SonViewModel(IEventAggregator ea)
    {
        this.ea = ea;
        //订阅这个类
        ea.GetEvent<MyMessager>().Subscribe(Reseived);
    }

    //处理接收数据的方法
    private void Reseived(string obj)
    {
        this.ReceivedMsg = obj;
    }
}

2.依赖注入

在依赖注入方面,可以选择不同的容器进行,这里选择的是Unity容器。

在App.xaml.cs中,注册需要的类

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }
	//管理注册的类
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
		//注册单例,可以手动new一个
        containerRegistry.RegisterInstance<MyService>(new MyService());
		//以单例模式注册主窗口
        containerRegistry.RegisterSingleton<MainViewModel>();
		//注册一个Dialog,后面会讲到
        containerRegistry.RegisterDialog<LoginDialog, LoginDialogViewModel>("loginDialog");
        containerRegistry.RegisterSingleton<ViewAViewModel>();
		//注册一个导航页面,可以使用导航系统获取这个页面
        containerRegistry.RegisterForNavigation<ViewA>();
    }
}

3.region+navigation

3.1.注册Region

prism将页面划分为不同的区域,使用该功能可以动态修改ui的界面显示的内容和控件。

我们可以先创建一个注册一个区域,这在xaml和后台代码中都可以实现。

<StackPanel>
    <Button Command="{Binding NavigateToCommand}" Content="navigate to viewA" />
	<!--  这里注册了两个区域,分别为RegionA和RegionB  -->
    <ContentControl Name="contentRegion" prism:RegionManager.RegionName="RegionA" />
    <ContentControl prism:RegionManager.RegionName="RegionB" />
</StackPanel>
//使用后台代码注册
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        RegionManager.SetRegionName(contentRegion, "RegionA");
    }
}

3.2.导航

我这里定义了一个叫ViewA的控件,可以使用RegionManager导航显示这个控件
在这里插入图片描述

在viewModel中使用命令显示控件

private DelegateCommand _navigateTo;
public DelegateCommand NavigateToCommand =>
    _navigateTo ?? (_navigateTo = new DelegateCommand(ExecuteNavigateToCommand));

void ExecuteNavigateToCommand()
{
	//在RegionA上显示控件ViewA
    regionManager.RequestNavigate("RegionA", "ViewA");
	//这个方法同样的效果
	regionManager.RegisterViewWithRegion<ViewA>("RegionA");
}

在这里插入图片描述

导航的同时,还可以有回调参数,传递数据等。。

4.DialogService

首先创建一个用户控件叫做LoginDialog和它的viewModel,然后在app.xaml.cs中注册,起个别名ligonDialog

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
		//注册起别名
        containerRegistry.RegisterDialog<LoginDialog, LoginDialogViewModel>("loginDialog");
    }
}

另外,loginDialogViewModel需要实现IDialogAware接口

public class LoginDialogViewModel : BindableBase, IDialogAware
{
    private string? _userName;

    public string? UserName
    {
        get { return _userName; }
        set { SetProperty(ref _userName, value); }
    }

    private string? _passwd;

    public string? Passwd
    {
        get { return _passwd; }
        set { SetProperty(ref _passwd, value); }
    }

    //返回消息时触发
    public DialogCloseListener RequestClose { get; }

    private DelegateCommand _save;

    public DelegateCommand SaveCommand =>
        _save ?? (_save = new DelegateCommand(ExecuteSaveCommand));

	//点击保存的按钮执行这个
	//这个方法向调用者发送了两个数据,并将返回值设为OK
    void ExecuteSaveCommand()
    {
        var param = new DialogParameters()
        {
            { "userName",UserName},
            { "passwd",Passwd}
    };
        RequestClose.Invoke(new DialogResult()
        {
            Result = ButtonResult.OK,
            Parameters = param
        });
    }

    private DelegateCommand _cancel;
    public DelegateCommand CancelCommand =>
        _cancel ?? (_cancel = new DelegateCommand(ExecuteCancelCommand));
	//点击取消的按钮执行这个
    void ExecuteCancelCommand()
    {
        RequestClose.Invoke(ButtonResult.Cancel);
    }
	//控制是否可以关闭
    public bool CanCloseDialog()
    {
        return true;
    }
	//关闭时执行这个
    public void OnDialogClosed()
    {
    }
	//dialog打开时会执行这个方法
    public void OnDialogOpened(IDialogParameters parameters)
    {
        //接收到的参数
        UserName = parameters.GetValue<string>("name");
        Passwd = parameters.GetValue<string>("pass");
    }
}

使用,调用这个dialog

//定义要传递的参数 
var param = new DialogParameters()
 {
     { "name","张三"},
     {"pass","12121" }
 };
//显示dialog,输入dialog的别名,传递的参数,dailog关闭时的回调
 dialogService.ShowDialog("loginDialog", param, (s) =>
 {
     ShowText = s.Parameters.GetValue<string>("userName");
 });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值