WPF框架Prism的使用 二

这篇具有很好参考价值的文章主要介绍了WPF框架Prism的使用 二。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

这是第二篇关于Prism-WPF的介绍,第一篇中我们简单介绍了Prism,然后讲述了如何搭建一个MVVM的简单页面程序。其实我写的文章就是把github上面的官方例子摘出来自己跑了一遍,然后加上了一些自己的理解,简单给大家分享一下。
下面放上传送门:
第一篇的链接
官方提供的示例.

Prism —— DelegateCommand

我们完成了View和ViewModel的关联之后,就是为了使用Binding功能,那么我们想要触发UI事件,并执行我们自己的方法,很多情况下都会需要用到Command。
比如对于一个按钮,<Button Content="你好" Command="{Binding SayHelloCommand}"/>
我们为其添加了Command的绑定,当我们触发按钮的点击事件的时候,Command的Action就会被执行,而Command则是一个需要继承接口ICommand的一个实例。
我们需要去定义我们自己的Command才能够去使用,当然也有各种各样的库,都提供了各种Command(我个人暂时没有了解过这些Command具体有什么区别)

这是Prism提供的Command类型——DelegateCommand

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                SetProperty(ref _isEnabled, value);
                ExecuteDelegateCommand.RaiseCanExecuteChanged();
            }
        }

        private string _updateText;
        public string UpdateText
        {
            get { return _updateText; }
            set { SetProperty(ref _updateText, value); }
        }


        public DelegateCommand ExecuteDelegateCommand { get; private set; }

        public DelegateCommand<string> ExecuteGenericDelegateCommand { get; private set; }        

        public DelegateCommand DelegateCommandObservesProperty { get; private set; }

        public DelegateCommand DelegateCommandObservesCanExecute { get; private set; }


        public MainWindowViewModel()
        {
            ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);

            DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute).ObservesProperty(() => IsEnabled);

            DelegateCommandObservesCanExecute = new DelegateCommand(Execute).ObservesCanExecute(() => IsEnabled);

            ExecuteGenericDelegateCommand = new DelegateCommand<string>(ExecuteGeneric).ObservesCanExecute(() => IsEnabled);
        }

        private void Execute()
        {
            UpdateText = $"Updated: {DateTime.Now}";
        }

        private void ExecuteGeneric(string parameter)
        {
            UpdateText = parameter;
        }

        private bool CanExecute()
        {
            return IsEnabled;
        }

DelegateCommand就是标准的ICommand,需要有一个Execute()的Action(Action是一个不需要返回值的泛型委托类型)和一个可选的CanExecute()的Func(Func是一个必须要有返回值的泛型委托类型)
因此,我们定义一个Command只需要如下代码

        public DelegateCommand ExecuteDelegateCommand { get; private set; }
        
        public MainWindowViewModel()
        {
            ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);
        }

那么诸如
ExecuteDelegateCommand.RaiseCanExecuteChanged();
.ObservesProperty(() => IsEnabled);
.ObservesCanExecute(() => IsEnabled);
又是做什么用的呢?

我们知道即使我们使用了Binding之后,也不是说视图和视图模型就会完全同步了,如果是视图改变了某些东西,视图模型会直接发生变化,但是如果是视图模型因为某些逻辑,改变了某个值,这时候,我们需要通过事件来主动通知视图需要做出某些改变,我们的ViewModel通常需要继承接口INotifyPropertyChanged,这个接口提供了通知View元素需要改变的事件。

那么同理,CanExecute会影响按钮是否被Enable的状态,这个状态会决定按钮能否被点击,同样是UI控件的变化,需要主动通知,而我们刚才写的那三种写法,就是通过不同的写法来通知UI的按钮需要调整Enable状态。

Prism —— PubSubEvent

我们能够让UI通过委托执行后台逻辑的代码之后呢,我们就要满足第二种需求,就是几个不同的页面直接的通信。想要实现页面之间的通信,我们有几种方法

  1. 让多个页面共享视图模型,不过这个方法比较丑陋,导致代码耦合度急剧上升,并且会导致代码混乱,优势就是没有什么额外的资源开销,属于效率最高的模式之一了
  2. 通过创建视图的时候传递参数,进行一次性的通讯,只需要传递一次的消息或者资源,我个人认为只需要传递参数就行
  3. 通过事件的发布和订阅来实现消息的传递,一般情况下,我们都会使用这种方式,而成熟的框架也会为我们实现好这一服务,而不需要我们自己手动写一套事件管理器,但是使用事件的时候需要额外注意,如果有需要,一定要及时注销的于事件的订阅,不然可能会导致内存泄露

PubSubEvent就是Prism提供的事件管理器,为我们提供了一个使用起来比较简单的视图通讯机制。

  1. 首先我们需要先定义自己的事件

        public class MessageSentEvent : PubSubEvent<string>
        {
        }
    
  2. 然后在需要触发消息的位置写如下代码

        public class MessageViewModel : BindableBase
        {
            IEventAggregator _ea;
    
            private string _message = "Message to Send";
            public string Message
            {
                get { return _message; }
                set { SetProperty(ref _message, value); }
            }
    
            public DelegateCommand SendMessageCommand { get; private set; }
    
            public MessageViewModel(IEventAggregator ea)
            {
                _ea = ea;
                SendMessageCommand = new DelegateCommand(SendMessage);
            }
    
            private void SendMessage()
            {
                _ea.GetEvent<MessageSentEvent>().Publish(Message);
            }
        }
    

    可以看到ViewModel的构造函数写了一个参数IEventAggregator ea这边构造函数是Prism框架自动实例化的,因此参数也是从IoC容器中自动找到后自动传递的。
    通过这个事件管理器来获取事件并调用Publish发送,我们就完成了消息的发布动作_ea.GetEvent<MessageSentEvent>().Publish(Message);

  3. 然后我们需要接收消息

        public class MessageListViewModel : BindableBase
        {
            IEventAggregator _ea;
    
            private ObservableCollection<string> _messages;
            public ObservableCollection<string> Messages
            {
                get { return _messages; }
                set { SetProperty(ref _messages, value); }
            }
    
            public MessageListViewModel(IEventAggregator ea)
            {
                _ea = ea;
                Messages = new ObservableCollection<string>();
    
                _ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);
            }
    
            private void MessageReceived(string message)
            {
                Messages.Add(message);
            }
        }
    

    同样的,_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived);通过调用Subscribe(),我们就完成了事件的监听,当事件触发时就会调用传入Subscribe的回调函数。

上面的例子大致是用于实现把一个消息框中的消息,存入另外一个页面里面的消息列表中去。

Prism —— Navigate

顾名思义,这就是页面导航功能,我不知道其他框架有没有提供,但是有了这个功能之后做页面导航或者页面切换十分方便。

我记得以前我做的页面切换显示就是自己通过修改Visibility或者修改ContentControl的内容来实现页面切换,现在我们将操作托管给Prism框架,我们只是把资源给框架,然后通知框架选择什么资源来显示。

Prism的Navigation通过如下两个步骤实现:

  1. 首先,我们需要创建一个Module
    在Module中注册我们的页面信息

        public class ModuleAModule : IModule
        {
            public void OnInitialized(IContainerProvider containerProvider)
            {
    
            }
    
            public void RegisterTypes(IContainerRegistry containerRegistry)
            {
                containerRegistry.RegisterForNavigation<ViewA>();
                containerRegistry.RegisterForNavigation<ViewB>();
            }
        }
    
  2. 将Module信息注册到App.xaml.cs中去

        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : PrismApplication
        {
            protected override Window CreateShell()
            {
                return Container.Resolve<MainWindow>();
            }
    
            protected override void RegisterTypes(IContainerRegistry containerRegistry)
            {
    
            }
    
            protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
            {
                moduleCatalog.AddModule<ModuleA.ModuleAModule>();
            }
        }
    
  3. 在主页面创建Region,用于显示子页面

<Window x:Class="BasicRegionNavigation.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/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <DockPanel LastChildFill="True">
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5" >
            <Button Command="{Binding NavigateCommand}" CommandParameter="ViewA" Margin="5">Navigate to View A</Button>
            <Button Command="{Binding NavigateCommand}" CommandParameter="ViewB" Margin="5">Navigate to View B</Button>
        </StackPanel>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="5"  />
    </DockPanel>
</Window>
  1. 在主页面视图模型中完成导航操作的实现
    通过代码中的_regionManager.RequestNavigate实现了通知region当前应该显示哪个页面。
    public class MainWindowViewModel : BindableBase
    {
        private readonly IRegionManager _regionManager;

        private string _title = "Prism Unity Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public DelegateCommand<string> NavigateCommand { get; private set; }

        public MainWindowViewModel(IRegionManager regionManager)
        {
            _regionManager = regionManager;

            NavigateCommand = new DelegateCommand<string>(Navigate);
        }

        private void Navigate(string navigatePath)
        {
            if (navigatePath != null)
                _regionManager.RequestNavigate("ContentRegion", navigatePath, NavigationComplete);
        }

        private void NavigationComplete(NavigationResult result)
        {
            System.Windows.MessageBox.Show(String.Format("Navigation to {0} complete. ", result.Context.Uri));
        }
    }

总结

现在我们已经学会绑定、命令、导航、消息传递等功能,已经能够实现一个比较复杂的应用了,这个Prism框架我个人觉得如果有一定基础,上手其实是很快的。
最后我写了一个样例工程,包含了上述功能的应用
Prism-Wpf-Demo文章来源地址https://www.toymoban.com/news/detail-846389.html

到了这里,关于WPF框架Prism的使用 二的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【WPF系列】【MVVM】Prism开源框架学习(一)

    第一章 【WPF系列】【MVVM】Prism开源框架学习(一) 这里先简单介绍下Prism是什么,怎么去学习,资料怎么获取。 Prism是一个用于构建WPF、UWP和Xamarin应用程序的开源框架,它提供了一套MVVM(Model-View-ViewModel)的架构模式,以及一组工具和库,帮助开发人员更容易地创建可扩展

    2024年02月13日
    浏览(29)
  • 基于Prism框架的WPF前端框架开发《知产代理数字化解决方案》

    最近新开发了一套WPF前端界面框架,叫《知产代理数字化解决方案》,采用了时下流行的Prism框架作为整个系统的基础架构,演示了Prism中的IRegionManager区域管理器、IDialogAware对话框、IDialogService对话框服务、IContainerExtension容器等用法。 系统对常用的控件进行了模板和样式开发

    2024年01月19日
    浏览(46)
  • WPF Prism的简单使用

    新建 WPF 项目,我是基于 .net 5.0-windows 创建的。 引入 Prism.DryIoc(8.1.97) 的 Nuget 包。 App.xaml 中引入命名空间。 将 App.xaml 中 Application 标签更改成 prism:PrismApplication 并去除 StartUri 属性,将 App.xaml.cs 中 Application 更改成 PrismApplication 。 实现 PrismApplication (实际上是 PrismApplicationBas

    2023年04月14日
    浏览(63)
  • wpf 项目中使用 Prism + MaterialDesign

      1.通过nuget安装MaterialDesign  2.通过nuget安装Prism 3.修改App.xmal  红色矩形框是需要更改的地方  3.修改app.xmal.cs文件 修改红色矩形框中的内容   至此,编译不出错,就算是好了 这时会出现两个窗体 记得删除  StartupUri=\\\"MainWindow.xaml\\\"即可

    2024年02月14日
    浏览(21)
  • Wpf 使用 Prism 实战开发Day10

    1-9章节已经把基本功能都做好了,但页面的数据是后台模拟生成的静态数据。接下来所有章节就是实现,页面的所有数据都是从数据库中获取,并且实现页面数据的持久化以及增删改查。 使用Sqlite 做为数据库  1.打开 MyToDo.Api项目,右键=》选择 管理NuGet 程序包 ,进行下载安

    2024年01月25日
    浏览(33)
  • Wpf 使用 Prism 实战开发Day08

    1.效果图 MemoView.xaml 页面代码      1. 在  ItemsControl 中,添加滚动条  ScrollViewer  这样使用 ScrollViewer 把内容区域包裹起来,就能让内容区域支持滚动了        2 . 添加滚动条后的效果图如下:  使用md 中的一个自带动画 md:TransitioningContent 来实现该功能  需要设置一个属性,

    2024年02月03日
    浏览(27)
  • Wpf 使用 Prism 实战开发Day03

    效果图:   创建 Models ,放置实体类。 实体类需要继承自 Prism 框架的  BindableBase ,目的是让实体类支持数据的动态变更!  例如: 系统导航菜单实体类 创建View文件夹  放置前端显示页面 。例如:创建首页: MainView.xaml 创建ViewModel 文件夹,放置前端逻辑处理类。意思是:有前端

    2024年02月08日
    浏览(31)
  • Wpf 使用 Prism 实战开发Day19

    由于待办事项功能页,数据已正常渲染出来了。但页面新增,查询,修改,删除等功能还未实现。本章节来实现页面的请求后台实现CURD(增删改查) 根据渲染出来的待办事项,点击对应的待办事项时,查找出该条数据,显展示在编辑窗口中。 同时在搜索框中输入的参数或选

    2024年04月23日
    浏览(22)
  • Wpf 使用 Prism 实战开发Day14

    备忘录控制器(MemoController)和待办事项控制器 (ToDoController)功能实现差不多一样。基本套路就是: 定义控制器(Controller) 定义数据传输层(Dto) 配置实体类(Entity)和数据传输类(Dto) 关系映射(Auto Mapper) 定义服务接口(IService) 实现服务接口 (Service) 把服务注入控

    2024年01月22日
    浏览(33)
  • Wpf 使用 Prism 实战开发Day12

    控制器类需要继承  ControllerBase 基类 需要添加 [ ApiController]  特性以及 [ Route]  特性 Route (路由) 特性参数规则,一般写法是  [Route(\\\"api/[controller]/[action]\\\")] 。也就是路由访问路径:前缀api/当前控制器/具体的方法 为了业务处理逻辑和控制器之间实现解耦。可以通过设计:

    2024年01月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包