更改基本 MVVM 的当前实现以遵循 SOLID 模式
Change current implementation of basic MVVM to adhere to SOLID pattern
我一直在使用在线提供的 MVVM 示例中通常提到的基本设计模式编写我所有的 MVVM 应用程序。我遵循的模式如下所述:
型号
此部分包括 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();
}
代理服务器
该层包含实现 IDataservice 的数据服务调用,例如:
public class DataService : IDataService
{
public async Task<Employee> GetEmployeeLst()
{
// Logic to get employee data from HTTPClient call
}
}
ViewModel
该层包含 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 还包含在 UI 触发事件时执行的 Delegatecommand。然后通过调用代理层中的 DataService 从服务器获取数据并执行业务逻辑并填充绑定到视图的 ViewModel 中的属性。对于每个视图,都有一个绑定到视图的 Datacontext 的 VM。
ViewModel 还负责启动动画我使用触发器启动故事板,它绑定到我在 VM 中的枚举以更改这些触发器的状态,例如:http://www.markermetro.com/2011/05/technical/mvvm-friendly-visual-state-management-with-windows-phone-7/
查看
在这一层中,我拥有所有视图、用户控件和业务逻辑,并实现了某些依赖项,如地理定位服务、AES 加密、视图之间的导航服务等。
每个视图都有 .xaml 和 .xaml.cs 文件。在 .xaml.cs 文件中,我将视图的数据上下文与 VM 绑定在一起,如下所示:
this.DataContext = App.IOConatiner.GetInstance<DashboardViewModel>();
从这里开始,所有绑定都会发生。
我的问题是最近我知道这个模式没有遵循我在这个问题的答案中了解到的 SOLID 设计模式:
我正在非常努力地按照我在上一个问题的答案中给出的建议来更改我的设计。但是我无法得到一些东西,比如:
当前 View Datacontext 绑定到 ViewModel,因此所有控件都由 VM 中的 属性 控制。我如何使用 Processor/Service 或 DialogHandler 将其更改为上述模式?
我正在使用绑定到 UI 元素的命令 属性 的 Delegatecommands。这些命令的执行会像动画一样发生某些动作,显示用户控件。如何在命令模式中执行?
我怎样才能开始改变我当前的实现以适应所有这些变化的最佳方法?
如果视图模型库 class 自己不使用这些服务,为什么要在视图模型库 class 中注入所有这些服务?
只需在确实需要这些服务的派生视图模型中注入您需要的服务。
首先回答你的问题3
How can I start changing my current implementation to accommodate all those changes with best possible approach?
这是您需要迈出的第一步。这不是对当前代码进行一些智能重构的情况。您将需要退后一步并设计应用程序。我曾经读过一些关于(重新)设计的好文章 blog。
在开始编写任何代码之前,定义要向用户显示多少种不同的基本视图类型?例如:
- 只显示(任何类型的)数据
- 编辑数据
- 提醒用户
- 要求用户输入
- ...
当您定义了不同的需求时,您可以将其转化为为它们所服务的工作量身定制的特定界面。例如,允许用户编辑数据的视图通常具有如下所示的界面:
public interface IEditViewModel<TEntity>
{
public EditResult<TEntity> EditEntity(TEntity entityToEdit)();
}
一旦设计的每个细节都到位,您必须决定如何向用户展示您的观点。我为此使用了另一个界面来为我处理这个任务。但您也可以决定让导航服务处理此类任务。
有了这个框架,您就可以开始编写实现代码了。
Currently View Datacontext is binded to ViewModel hence all the controls are controlled by a property in VM. How would I change this to your above mentioned pattern with Processor/Service or DialogHandler?
这在本次设计中不会改变。您仍然会将视图绑定到视图模型并将数据上下文设置为视图模型。有了很多视图,使用像 Caliburn Micro 这样的 MVVM 框架就会派上用场。基于 Convention over Configuration,这将为您完成很多 MVVM 工作。从这个模型开始,会使学习曲线更高,所以我的建议是手工开始。您将通过这种方式了解在此类 MVVM 工具的掩护下发生的事情。
I am using Delegatecommands which are binded to command property of UI element. Execution of these command certain action happens like animation, usercontrol is displayed. How to do it in command pattern?
我不确定你在这里提到的命令模式是否是我在之前的回答中建议你的command pattern。如果是这样,我认为您需要重新阅读此博客,因为这与我认为您在这个问题中的意思完全无关。
动画和这类东西是视图的责任,而不是视图模型。所以视图应该处理所有这些东西。 XAML 有很多方法可以解决这个问题。我在这里无法解释。一些想法:Triggers, Dependency Properties
另一种选择:代码隐藏!如果逻辑纯粹是与视图相关的 IMO,那么将此代码放在视图后面的代码中并不是致命的罪过。只是不要被诱惑去做一些灰色地带的事情!
对于仅在您的视图模型中执行方法调用的命令,ICommand 仍然是可能的,并且像 Caliburn 这样的 MVVM 工具将自动执行此操作...
还有:松开底座 class...
我一直在使用在线提供的 MVVM 示例中通常提到的基本设计模式编写我所有的 MVVM 应用程序。我遵循的模式如下所述:
型号
此部分包括 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();
}
代理服务器
该层包含实现 IDataservice 的数据服务调用,例如:
public class DataService : IDataService
{
public async Task<Employee> GetEmployeeLst()
{
// Logic to get employee data from HTTPClient call
}
}
ViewModel
该层包含 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 还包含在 UI 触发事件时执行的 Delegatecommand。然后通过调用代理层中的 DataService 从服务器获取数据并执行业务逻辑并填充绑定到视图的 ViewModel 中的属性。对于每个视图,都有一个绑定到视图的 Datacontext 的 VM。 ViewModel 还负责启动动画我使用触发器启动故事板,它绑定到我在 VM 中的枚举以更改这些触发器的状态,例如:http://www.markermetro.com/2011/05/technical/mvvm-friendly-visual-state-management-with-windows-phone-7/
查看
在这一层中,我拥有所有视图、用户控件和业务逻辑,并实现了某些依赖项,如地理定位服务、AES 加密、视图之间的导航服务等。
每个视图都有 .xaml 和 .xaml.cs 文件。在 .xaml.cs 文件中,我将视图的数据上下文与 VM 绑定在一起,如下所示:
this.DataContext = App.IOConatiner.GetInstance<DashboardViewModel>();
从这里开始,所有绑定都会发生。
我的问题是最近我知道这个模式没有遵循我在这个问题的答案中了解到的 SOLID 设计模式:
我正在非常努力地按照我在上一个问题的答案中给出的建议来更改我的设计。但是我无法得到一些东西,比如:
当前 View Datacontext 绑定到 ViewModel,因此所有控件都由 VM 中的 属性 控制。我如何使用 Processor/Service 或 DialogHandler 将其更改为上述模式?
我正在使用绑定到 UI 元素的命令 属性 的 Delegatecommands。这些命令的执行会像动画一样发生某些动作,显示用户控件。如何在命令模式中执行?
我怎样才能开始改变我当前的实现以适应所有这些变化的最佳方法?
如果视图模型库 class 自己不使用这些服务,为什么要在视图模型库 class 中注入所有这些服务?
只需在确实需要这些服务的派生视图模型中注入您需要的服务。
首先回答你的问题3
How can I start changing my current implementation to accommodate all those changes with best possible approach?
这是您需要迈出的第一步。这不是对当前代码进行一些智能重构的情况。您将需要退后一步并设计应用程序。我曾经读过一些关于(重新)设计的好文章 blog。
在开始编写任何代码之前,定义要向用户显示多少种不同的基本视图类型?例如:
- 只显示(任何类型的)数据
- 编辑数据
- 提醒用户
- 要求用户输入
- ...
当您定义了不同的需求时,您可以将其转化为为它们所服务的工作量身定制的特定界面。例如,允许用户编辑数据的视图通常具有如下所示的界面:
public interface IEditViewModel<TEntity>
{
public EditResult<TEntity> EditEntity(TEntity entityToEdit)();
}
一旦设计的每个细节都到位,您必须决定如何向用户展示您的观点。我为此使用了另一个界面来为我处理这个任务。但您也可以决定让导航服务处理此类任务。
有了这个框架,您就可以开始编写实现代码了。
Currently View Datacontext is binded to ViewModel hence all the controls are controlled by a property in VM. How would I change this to your above mentioned pattern with Processor/Service or DialogHandler?
这在本次设计中不会改变。您仍然会将视图绑定到视图模型并将数据上下文设置为视图模型。有了很多视图,使用像 Caliburn Micro 这样的 MVVM 框架就会派上用场。基于 Convention over Configuration,这将为您完成很多 MVVM 工作。从这个模型开始,会使学习曲线更高,所以我的建议是手工开始。您将通过这种方式了解在此类 MVVM 工具的掩护下发生的事情。
I am using Delegatecommands which are binded to command property of UI element. Execution of these command certain action happens like animation, usercontrol is displayed. How to do it in command pattern?
我不确定你在这里提到的命令模式是否是我在之前的回答中建议你的command pattern。如果是这样,我认为您需要重新阅读此博客,因为这与我认为您在这个问题中的意思完全无关。
动画和这类东西是视图的责任,而不是视图模型。所以视图应该处理所有这些东西。 XAML 有很多方法可以解决这个问题。我在这里无法解释。一些想法:Triggers, Dependency Properties
另一种选择:代码隐藏!如果逻辑纯粹是与视图相关的 IMO,那么将此代码放在视图后面的代码中并不是致命的罪过。只是不要被诱惑去做一些灰色地带的事情!
对于仅在您的视图模型中执行方法调用的命令,ICommand 仍然是可能的,并且像 Caliburn 这样的 MVVM 工具将自动执行此操作...
还有:松开底座 class...