Change current implementation of basic MVVM to adhere to SOLID pattern

拥有回忆 提交于 2019-12-02 13:11:51

问题


I have been writing all my MVVM application with basic design pattern generally mentioned in MVVM examples available online. The pattern that I am following is described below:

Model

This section include DTO classes with their properties and Interfaces IDataService and like:

 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

This layer contains Dataservice calls which implement IDataservice like:

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

ViewModel

This layer contains ViewModel and reference to Model and Proxy layer from which all data is received:

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
}

All the ViewModel inherits BaseViewModel. Each viewModel also contains Delegatecommand which is executed when UI triggers an event. Which then fetches the data from the server by calling DataService in proxy layer and perform business logic and populates the properties in ViewModel which is binded to the view. For each View there is a VM which is binded to the Datacontext of the View. ViewModel is also responsible for starting an animation I have used trigger to start storyboard which is binded to my enums in VM for state change of these trigger as in example in: http://www.markermetro.com/2011/05/technical/mvvm-friendly-visual-state-management-with-windows-phone-7/

View

In this layer I have all my Views, Usercontrols and business logic with implementation of certain dependencies like GeoLocation Service, AES encryption, NavigationService between Views etc.

Every View has .xaml and .xaml.cs file. In .xaml.cs file I have binded the data context of the view with VM like this:

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

and from here on all binding happens.

My problem is that recently I had the knowledge that this pattern is not following a SOLID design pattern which I got know in this answer of my question: Simple Injector inject multiple dependency in BaseClass

I am trying very hard to change my design as per the suggestion given in my previous question's answer. But I am not able to get some of the things like:

  1. 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?

  2. 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?

  3. How can I start changing my current implementation to accommodate all those changes with best possible approach?


回答1:


First of all an answer to your question 3

How can I start changing my current implementation to accommodate all those changes with best possible approach?

This is the very first step you need to take. It is not a case of some smart refactoring of your current code. You will need to take a step back and design the application. I once read some nice blog about (re)design.

Before starting to write any code, define how many different basic types of views you will want to show to the user? E.g.:

  1. Just show (any type of) data
  2. Edit data
  3. Alert user
  4. Ask user for input
  5. ...

When you defined your different requirements, you can translate this to specific interfaces that are tailor made for the job they serve. For example a view that lets the user edit data will typically have an interface that will look something like:

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

Once you every detail of this design in place, you must decide how you will show your views to the user. I used another interface for this to handle this task for me. But you could also decide to let a navigation service handle this kind of task.

With this framework in place, you can start coding your implementations.

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?

This will not change in this design. You will still bind your view to your viewmodel and set the datacontext to the viewmodel. With a lot of views the use of an MVVM framework like Caliburn Micro will come in handy. This will do a lot of the MVVM stuff for you, based on Convention over Configuration. To start with this model, would make the learning curve even higher, so my advice to start of by hand. You will learn this way what happens under the covers of such an MVVM tool.

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?

I'm not sure if the command pattern you mention here is the command pattern I advised you in the previous answer. If so, I think you need to reread this blog, because this is totally unrelated to the commands I think you mean in this question.

Animation and that sort of stuff is the responsibility of the view, not the viewmodel. So the view should handle all this stuff. XAML has a lot of ways to handle this. More than I can explain here. Some ideas: Triggers, Dependency Properties

Another option: Code behind! If the logic is purely view related IMO it is not a mortal sin to place this code in the code behind of your view. Just don't be temped to do some gray area stuff!

For commands that just perform a method call in your viewmodel, ICommand is still possible and MVVM tools like Caliburn will do this automagically...

And still: Loose the base class....




回答2:


Why are you injecting all these services in your viewmodel base class if the viewmodel base class does not make use of these services himself ?

Just inject the services you need in the derived viewmodels that do need those services.



来源:https://stackoverflow.com/questions/28398363/change-current-implementation-of-basic-mvvm-to-adhere-to-solid-pattern

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!