【WPF】Prism学习(十)

devtools/2024/11/26 0:39:44/

Prism_MVVM_0">Prism MVVM

在这里插入图片描述

1.BindableBase

1.1. BindableBase的作用

  • Prism库提供了一个基础类BindableBase,这个类实现了INotifyPropertyChanged接口。这个接口允许ViewModel(视图模型)通知视图(View)当属性(Property)发生变化时,以便视图可以更新显示。

Prism_7">1.2. Prism的接口驱动特性

  • Prism框架的许多功能,如响应生命周期事件、导航等,都是基于接口的。这意味着Prism并不强制要求开发者使用特定的基础类。

1.3. BindableBase的可选性

  • 尽管Prism提供了BindableBase作为INotifyPropertyChanged的实现,以帮助开发者,但它并不强制要求开发者必须使用这个类。开发者可以根据自己的需要选择任何基础类,甚至不使用任何基础类(尽管通常不推荐这样做)。

2.创建属性

在继承自BindableBase的类中创建属性,并确保这些属性的变化能够通知到用户界面(UI)。具体来说,它介绍了如何使用SetProperty方法来设置属性值,并确保属性有一个公共的属性和一个私有的后端字段(backing field)。

2.1. 创建属性(Creating Properties)

  • 当你在继承自BindableBase的类中创建属性时,如果你希望这些属性的变化能够通知到UI,你应该使用SetProperty方法来设置这些变化。
  • 每个属性都应该有一个公共的属性接口(供外部访问和设置),以及一个私有的后端字段,用于实际存储属性值。

2.2. 示例代码

public class ViewAViewModel : BindableBase
{private string _message;public string Message{get => _message;set => SetProperty(ref _message, value);}
}
  • 代码示例展示了一个名为ViewAViewModel的类,它继承自BindableBase
  • 这个类中有一个名为_message的私有字符串字段,用于存储消息内容。
  • 同时,它有一个公共的字符串属性Message,用于获取和设置消息内容。
  • Message属性的set访问器中,使用了SetProperty方法来更新_message字段的值。SetProperty方法接受三个参数:一个引用传递的当前值(ref _message),新值(value),以及一个可选的回调委托,当属性值变化时执行。

2.3. SetProperty方法的作用

  • SetProperty方法不仅设置属性的新值,还自动比较新旧值,只有在值实际变化时才触发INotifyPropertyChanged事件,这样可以避免不必要的事件触发。
  • 如果直接设置值并调用RaisePropertyChanged,将失去这种内置的值比较功能,可能导致即使值未变化也触发事件。

3.为什么使用SetProperty

在实现MVVM模式时,使用SetProperty方法来设置属性值是更好的选择,而不是直接调用RaisePropertyChanged方法。

首先,提出了一个问题:“为什么使用SetProperty?毕竟你可以直接调用RaisePropertyChanged,不是吗?”然后,给出了简短的答案:虽然你可以这样做,但通常不推荐,因为你将失去内置的EqualityComparerEqualityComparer的作用是确保如果设置了多次相同的值,INotifyPropertyChanged接口只会在值第一次改变时触发PropertyChanged事件。

接下来,通过一个代码示例来说明直接调用RaisePropertyChanged的问题:

public class ViewAViewModel : BindableBase
{private string _message;public string Message{get => _message;set{// 不要这样做!_message = value;RaisePropertyChanged();}}
}

这种代码在生产环境中很常见,但这种代码是有根本缺陷的,过于冗长,并且会导致不必要的PropertyChanged事件被触发。因此,你应该始终围绕SetProperty方法来构建你的代码流程。

总结一下,使用SetProperty而不是直接调用RaisePropertyChanged的原因是:

  1. SetProperty内置了EqualityComparer,可以避免在属性值没有实际改变时触发PropertyChanged事件。
  2. 直接调用RaisePropertyChanged会导致代码过于冗长,并且可能会引发不必要的事件。
  3. 使用SetProperty可以使代码更加简洁,并且遵循MVVM的最佳实践。

4.在属性变化时执行委托

public abstract class ViewModelBase : BindableBase, IActiveAware
{private bool _isActive;public bool IsActive{get => _isActive;set => SetProperty(ref _isActive, value, () => {if (value)OnIsActive();elseOnIsNotActive();});}protected virtual void OnIsActive() { }protected virtual void OnIsNotActive() { }
}

4.1. 代码示例

  • ViewModelBase 类继承自 BindableBase 类并实现了 IActiveAware 接口。
  • BindableBase 类是一个基类,它实现了 INotifyPropertyChanged 接口,允许对象通知绑定的UI元素属性值的变化。
  • IActiveAware 接口用于管理视图模型的激活状态。

4.2. IsActive 属性

  • IsActive 属性是一个布尔值,表示视图模型是否处于激活状态。
  • IsActive 属性的 set 访问器中,使用了 SetProperty 方法来更新 _isActive 私有字段的值,并注册了一个回调函数。
  • SetProperty 方法接受三个参数:一个引用传递的当前值、新值和一个可选的回调函数。

4.3. 回调函数

  • IsActive 属性的值被设置时,SetProperty 方法会检查新值和旧值是否相等。如果不相等,它会触发 PropertyChanged 事件,并执行提供的回调函数。
  • 在这个例子中,回调函数是一个匿名函数,它检查 IsActive 的新值:
    • 如果新值为 true,则调用 OnIsActive 方法。
    • 如果新值为 false,则调用 OnIsNotActive 方法。

4.4. OnIsActive 和 OnIsNotActive 方法

  • 这两个方法是用来响应激活状态变化的虚拟保护方法。你可以在派生类中重写这些方法来执行特定的逻辑。

相关链接

  • 介绍(Introduction)
  • 命令(Commands)
    • 命令(Commanding)
    • 复合命令(Composite Commands)
    • 异步命令(Async Commands)
    • 错误处理(Error Handling)
  • 依赖注入(Dependency Injection)
    • 依赖注入(Dependency Injection)
    • 注册类型(Registering Types)
    • 处理解析错误
    • ContainerLocator
  • MVVM
    • BindableBase

http://www.ppmy.cn/devtools/136978.html

相关文章

MongoDB相关问题

视频教程 【GeekHour】20分钟掌握MongoDB Complete MongoDB Tutorial by Net Ninja MongoDB开机后调用缓慢的原因及解决方法 问题分析: MongoDB开机后调用缓慢,通常是由于以下原因导致: 索引重建: MongoDB在启动时会重建索引…

揭秘区块链隐私黑科技:零知识证明如何改变未来

文章目录 1. 引言:什么是零知识证明?2. 零知识证明的核心概念与三大属性2.1 完备性(Completeness)2.2 可靠性(Soundness)2.3 零知识性(Zero-Knowledge) 3. 零知识证明的工作原理4. 零…

Python Selenium:Web自动化测试与爬虫开发

Python Selenium:Web自动化测试与爬虫开发 Python Selenium:Web自动化测试与爬虫开发安装Selenium设置WebDriver基础示例页面元素交互处理JavaScript和Cookies浏览器控制屏幕截图Headless Mode结束会话错误处理与调试 ***本文由AI辅助生成*** Python Se…

windowsC#-在异步任务完成时处理

通过使用 Task.WhenAny,可同时启动多个任务,并在它们完成时逐个对它们进行处理,而不是按照它们的启动顺序进行处理。 下面的示例使用查询来创建一组任务。 每个任务都下载指定网站的内容。 在对 while 循环的每次迭代中,对 WhenA…

前端框架 Redux tool RTK 总结

目录 一、安装依赖 二、创建redux仓库的目录结构 三、createSlice 四、configureStore 五、配置全局仓库标签 六、useSelector 七、useDispatch Redux Tool官网:Redux - A JS library for predictable and maintainable global state management | Redux 一…

gitHub常用操作

gitHub常用操作 1、把项目拉下来2、添加上游仓库3、进入分支4、从上游仓库拉取更新 1、把项目拉下来 在对应项目的右上角点击fork,fork下来:将远程仓库复制到个人仓库 在创建好的分支文件夹下使用 git clone自己远程仓库下的http地址(fork…

手机发展史介绍

手机,这个曾经在电影和科幻小说中出现的高科技产品,如今已经渗透进了我们生活的每个角落。从单纯的通讯工具到如今集成了通讯、娱乐、工作、社交等多种功能的智能终端,手机的发展史也是人类科技进步的缩影。本文将从手机的发展历程、技术革新…

在 ARM 平台上如何实现Linux系统的1秒启动

在ARM平台上实现Linux系统的1秒启动,是一项涉及深层次优化的挑战。这不仅需要对系统的各个层面进行精细调整,还需要确保在保持系统稳定性的同时,实现快速启动。以下是实现这一目标的关键步骤和优化工作: 1. 精简U-Boot启动过程 …