更改基本 MVVM 的当前实现以遵循 SOLID 模式

2023-11-29

我一直在使用在线提供的 MVVM 示例中通常提到的基本设计模式编写所有 MVVM 应用程序。我遵循的模式如下所述:

Model

本节包括 DTO 类及其属性和接口 IDataService 等:

 public class Employee
 {
   public string EmployeeName { get; set; }
   public string EmployeeDesignation { get; set; }
   public string EmployeeID { get; set; }
 }

public interface IDataService
{
  public Task<Employee> GetEmployeeLst();
}

Proxy

该层包含实现 IDataservice 的 Dataservice 调用,例如:

public class DataService : IDataService
{
   public async Task<Employee> GetEmployeeLst()
   {
     // Logic to get employee data from HTTPClient call
   }
}

视图模型

该层包含 ViewModel 以及对模型和代理层的引用,从中接收所有数据:

public class BaseViewModel
{
    public BaseViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt, IGeoLocationService geoLocation, IMessageBus msgBus, ISmartDispatcher smtDispatcher)
    {
    }

    // This also include common methods and static properties that are shared among most of the ViewModels
}

所有的ViewModel都继承BaseViewModel。每个 viewModel 还包含 Delegatecommand,该命令在 UI 触发事件时执行。然后通过调用代理层中的 DataService 从服务器获取数据并执行业务逻辑并填充绑定到视图的 ViewModel 中的属性。对于每个视图,都有一个绑定到该视图的数据上下文的虚拟机。 ViewModel 还负责启动动画我已经使用触发器来启动故事板,该故事板绑定到 VM 中的枚举以更改这些触发器的状态,如下所示:http://www.markermetro.com/2011/05/technical/mvvm-friend-visual-state-management-with-windows-phone-7/

View

在这一层中,我拥有所有视图、用户控件和业务逻辑,并实现了某些依赖项,例如地理位置服务、AES 加密、视图之间的导航服务等。

每个视图都有 .xaml 和 .xaml.cs 文件。在 .xaml.cs 文件中,我将视图的数据上下文与 VM 绑定在一起,如下所示:

this.DataContext = App.IOConatiner.GetInstance<DashboardViewModel>();

从这里开始,所有的绑定都会发生。

我的问题是,最近我知道这种模式不遵循可靠的设计模式,这是我在问题的答案中了解到的:简单注入器在 BaseClass 中注入多个依赖项

我正在非常努力地根据我上一个问题的答案中给出的建议来改变我的设计。但我无法得到一些东西,例如:

  1. 目前,View Datacontext 绑定到 ViewModel,因此所有控件都由 VM 中的属性控制。我如何使用处理器/服务或 DialogHandler 将其更改为上述模式?

  2. 我正在使用绑定到 UI 元素的命令属性的 Delegatecommands。执行这些命令会发生某些操作,例如动画,显示用户控件。如何在命令模式下做到这一点?

  3. 我如何开始改变当前的实现,以尽可能最佳的方法来适应所有这些变化?


首先回答你的问题3

我如何开始改变当前的实现,以尽可能最佳的方法来适应所有这些变化?

这是您需要采取的第一步。这不是对当前代码进行一些智能重构的情况。您需要退后一步来设计应用程序。我曾经读过一些不错的blog关于(重新)设计。

在开始编写任何代码之前,定义要向用户显示多少种不同的基本类型的视图?例如。:

  1. 仅显示(任何类型的)数据
  2. 编辑数据
  3. 提醒用户
  4. 询问用户输入
  5. ...

当您定义不同的需求时,您可以将其转换为针对其所服务的工作量身定制的特定界面。例如,允许用户编辑数据的视图通常具有如下所示的界面:

public interface IEditViewModel<TEntity>
{
    public EditResult<TEntity> EditEntity(TEntity entityToEdit)();
}

一旦设计的每个细节都到位,您必须决定如何向用户展示您的视图。我使用了另一个界面来为我处理这个任务。但您也可以决定让导航服务来处理此类任务。

有了这个框架,您就可以开始编写实现代码了。

目前,View Datacontext 绑定到 ViewModel,因此所有控件都由 VM 中的属性控制。我如何使用处理器/服务或 DialogHandler 将其更改为上述模式?

这在本设计中不会改变。您仍然会将视图绑定到视图模型,并将数据上下文设置为视图模型。有了很多视图,使用像 Caliburn Micro 这样的 MVVM 框架就会派上用场。这将为你做很多 MVVM 的事情,基于约定优于配置。从这个模型开始,会使学习曲线更高,所以我建议从手工开始。您将通过这种方式了解 MVVM 工具背后发生的事情。

我正在使用绑定到 UI 元素的命令属性的 Delegatecommands。执行这些命令会发生某些操作,例如动画,显示用户控件。如何在命令模式下做到这一点?

我不确定你在这里提到的命令模式是否是命令模式我在之前的回答中建议过你。如果是这样,我认为您需要重新阅读此博客,因为这与我认为您在这个问题中指的命令完全无关。

动画之类的东西是视图的责任,而不是视图模型的责任。所以视图应该处理所有这些东西。 XAML 有很多方法来处理这个问题。我无法在这里解释更多。一些想法:Triggers, 依赖属性

另一种选择:代码隐藏!如果逻辑纯粹与视图相关(IMO),那么将此代码放在视图后面的代码中并不是一个大罪。只是不要想做一些灰色地带的事情!

对于仅在视图模型中执行方法调用的命令,ICommand 仍然是可能的,并且像 Caliburn 这样的 MVVM 工具会自动执行此操作...

仍然:松开基类......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改基本 MVVM 的当前实现以遵循 SOLID 模式 的相关文章

  • 如何让窗口最大化时所有控件按比例调整大小?

    当我单击最大化按钮时 窗口最大化 但控件未按比例调整大小 使控件相应调整大小的最佳方法是什么 我正在使用MVVM 这是我的代码
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 如何修复此错误“GDI+ 中发生一般错误”?

    从默认名称打开图像并以默认名称保存 覆盖它 我需要从 Image Default jpg 制作图形 将其放在 picturebox1 image 上并在 picurebox1 上绘制一些图形 它有效 这不是我的问题 但我无法保存 pictu
  • 在 Unity 进程和另一个 C# 进程之间进行本地 IPC 的最快方法 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我希望每秒大约 30 次从 C 应用程序向我的 Unity 应用程序传送大量数据 由于 Unity 不支持映射内存和管道 我考虑了 t
  • C++中的类查找结构体数组

    我正在尝试创建一个结构数组 它将输入字符串链接到类 如下所示 struct string command CommandPath cPath cPathLookup set an alarm AlarmCommandPath send an
  • 将 System.Windows.Input.KeyEventArgs 键转换为 char

    我需要将事件参数作为char 但是当我尝试转换 Key 枚举时 我得到的字母和符号与传入的字母和符号完全不同 如何正确地将密钥转换为字符 这是我尝试过的 ObserveKeyStroke this new ObervableKeyStrok
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • 未定义的行为或误报

    我 基本上 在野外遇到过以下情况 x x 5 显然 它可以在早期版本的 gcc 下编译干净 在 gcc 4 5 1 下生成警告 据我所知 警告是由 Wsequence point 生成的 所以我的问题是 这是否违反了标准中关于在序列点之间操
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 在一个字节中存储 4 个不同的值

    我有一个任务要做 但我不知道从哪里开始 我不期待也绝对不想要代码中的答案 我想要一些关于该怎么做的指导 因为我感到有点失落 将变量打包和解包到一个字节中 您需要在一个字节中存储 4 个不同的值 这些值为 NAME RANGE BITS en
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 用于 C# 的 TripleDES IV?

    所以当我说这样的话 TripleDES tripledes TripleDES Create Rfc2898DeriveBytes pdb new Rfc2898DeriveBytes password plain tripledes Ke
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0
  • Linq-to-entities,在一个查询中获取结果+行数

    我已经看到了有关此事的多个问题 但它们已经有 2 年 或更长 的历史了 所以我想知道这方面是否有任何变化 基本思想是填充网格视图并创建自定义分页 所以 我还需要结果和行数 在 SQL 中 这将类似于 SELECT COUNT id Id N
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐

  • 以编程方式将新列添加到 DataGridView

    我有一个绑定到 DataTable 的 DataGridView DataTable 由数据库查询填充 该表包含一个名为 BestBefore 的列 BestBefore 是格式化为字符串的日期 SQLite 没有日期类型 我想以编程方式向
  • 使用以正则表达式作为键的字典进行多个正则表达式替换

    我想使用多个正则表达式对字符串进行多次替换 我还想在一次传递中进行替换 以避免创建字符串的多个实例 假设对于参数 我想进行下面的替换 同时避免多次使用 re sub 无论是显式使用还是循环使用 import re text local fo
  • 带有 jquery.ajax() 的跨域“授权”标头

    我正在尝试发送跨源域并添加自定义 授权 标头 请参阅下面的代码 Error XMLHttpRequest 无法加载 url Access Control Allow Headers 不允许请求标头字段授权 function loadJson
  • 类路径和源路径之间的区别?

    我对类路径和源路径有这种困惑 我参考了这些链接 也是 但我没做对 参考 javac 的类路径和源路径选项之间的差异 sourcepath 与 classpath 关于自动重新编译 我无法发现 javac 的 classpath 和 sour
  • Firefox 扩展开发 - 数据存储 - Firefox 首选项是个好地方吗?

    我开发了一个 Firefox 插件 需要在本地计算机中保存一些用户数据 现在 我使用 Firefox 提供的文件系统功能在用户系统中创建一些文件夹和文件 可移植性是一个问题 我是为 Windows XP 设计的 但是 Vista 的文件夹结
  • 在准备好的 mysqli 语句中多次使用一个参数

    是否可以在准备好的参数中使用一个参数mysqli 多次声明仅绑定一次 像这样的东西 stmt mysqli gt prepare SELECT FROM user WHERE age BETWEEN 1 2 AND 1 2 stmt gt
  • 仅将字典的最新值添加到列表中[重复]

    这个问题在这里已经有答案了 通过 for 循环创建字典列表 我一直在尝试通过 for 循环创建字典列表 代码如下所示 a x y z b 1 2 3 dict1 superlist for i in range 0 len a dict1
  • javaassist 和 cglib 之间的区别

    我学习hibernate 我了解到hibernate已经停止使用cglib并切换到javaassist 我还了解到javaassist和cglib用于代理生成 所以我想知道这两者是如何工作的以及哪一个更好 他们的工作方式有什么区别 Cgli
  • 将 R 变量传递给 sql 语句

    有没有办法将 R 中定义的变量传递给 sqldf 包中的 SQL 语句 我必须运行下面的代码 并将 v 变量作为 v 传递给 sql select 语句 for i in 1 50 v lt i 450 temp lt sqldf sele
  • sys_brk 的对齐要求是什么

    我正在使用 sys brk 系统调用动态分配堆中的内存 我注意到 在获取当前中断位置时 我通常会得到与此类似的值 mov rax 0x0C mov rdi 0x00 syscall 结果是 rax 0x401000 该值通常按 512 字节
  • javascript 找不到图像文件(Rails 4 应用程序)

    我有一个 Ruby on Rails 4 应用程序 在app assets javascripts 我创建了一个文件map js在谷歌地图上绘制一些自定义标记 var marker new google maps Marker dragga
  • 对于不相等的列表,eq 返回 true

    我有一段奇怪的代码需要调试 我认为它应该抛出异常 但它却产生了完全奇怪的结果 将其简化为这两行 EDU gt gt A 0 0 A 0 0 EDU gt gt A 1 2 A 2 1 ans 1 为什么两个不相等的逗号分隔列表的比较是正确的
  • Python - 如何跳过特定的 JSON 元素?

    query pages 7412236 pageid 7412236 ns 0 title Steve Jobs extract p b Steven Paul b b Steve b b Jobs b u02c8d u0292 u0252
  • jQuery 中的 onHide() 类型事件

    有谁知道一个onHide jQuery 中的事件或类似的东西 I tried this bind hide function console log asdasda 但显然这不起作用 Edit 只是为了澄清 它是使用 CSS 隐藏的disp
  • 在同一脚本中启动并调用 Ruby HTTP 服务器

    我想知道如何启动 Ruby Rack 应用程序 例如 Sinatra 并在同一脚本中使用 Net HTTP 或类似方法调用它 当然我可以做类似的事情 require sinatra base require net http t Threa
  • 将 json 反序列化为 pojo,其中 json 字段具有不同的数据类型

    我正在尝试将 json 反序列化为 java pojo 但我无法理解应该如何开始创建一个可用于反序列化 json 的 java 对象 如下所示 links version 2 executionState completed outputs
  • Selenium WebDriver - Java - 单击按钮

    我正在尝试单击一些按钮 并使用 twitch 上的 关注 按钮作为示例 我使用 Selenium IDE 尝试获取按钮的 xpath 我得到的 xpath 是 span id ember637 a span 如果我转到 FireFox 并复
  • 具有缺失值的多元 LSTM

    我正在使用 LSTM 解决时间序列预测问题 输入包含多个特征 因此我使用多元 LSTM 问题是有一些缺失值 例如 Feature 1 Feature 2 Feature n 1 2 4 nan 2 5 8 10 3 8 8 5 4 nan
  • EACCES:权限被拒绝,打开 '/usr/local/lib/node_modules/npm/bin/npm-cli.js'

    你好 先生 我是 docker 新手 我正在使用 ubuntu budgie linux 20 04 我的 docker 版本是Docker version 18 09 9 build 1752eb3我已经使用 snap 包管理器安装了 d
  • 更改基本 MVVM 的当前实现以遵循 SOLID 模式

    我一直在使用在线提供的 MVVM 示例中通常提到的基本设计模式编写所有 MVVM 应用程序 我遵循的模式如下所述 Model 本节包括 DTO 类及其属性和接口 IDataService 等 public class Employee pu