简体   繁体   English

WPF MVVM中ViewModel的Mediatr通知

[英]Mediatr Notifications on ViewModel in WPF MVVM

While implementing a WPF Application I stumbled on the problem that my application needs some global data in every ViewModel. 在实现WPF应用程序时,我偶然发现了我的应用程序在每个ViewModel中都需要一些全局数据的问题。 However some of the ViewModels only need reading access while other need read/write access for this Field. 但是,某些ViewModel仅需要对该字段的读取访问权限,而另一些需要对该字段的读/写访问权限。 At First I stumbled upon the Microsoft Idea of a SessionContext like so: 最初,我偶然发现了Microsoft的SessionContext想法,如下所示:

public class SessionContext
    {
        #region Public Members
        public static string UserName { get; set; }
        public static string Role { get; set; }

        public static Teacher CurrentTeacher { get; set; }
        public static Parent CurrentParent { get; set; }
        public static LocalStudent CurrentStudent { get; set; }

        public static List<LocalGrade> CurrentGrades { get; set; }
        #endregion

        #region Public Methods
        public static void Logon(string userName, string role)
        {
            UserName = userName;
            Role = role;
        }

        public static void Logoff()
        {
            UserName = "";
            Role = "";
            CurrentStudent = null;
            CurrentTeacher = null;
            CurrentParent = null;
        }
        #endregion
}

This isn't (in my Opinion at least) nicely testable and it gets problematic in case my global data grows (A think that could likely happen in this application). 这(至少在我看来)是无法很好测试的,并且如果我的全局数据增长(这可能会在此应用程序中发生),就会出现问题。 The next thing I found was the implementation of a Mediator/the Mediator Pattern from this link . 我发现的下一件事情是从此链接实现Mediator / Mediator模式。 I liked the Idea of the Design Norbert is going here and thought about implementing something similar for my project. 我喜欢“设计理念”,诺伯特(Norbert)会在这里思考如何为我的项目实施类似的设计。 However in this project I am already using the impressive Mediatr Nuget Package and that is also a Mediator implementation. 但是,在这个项目中,我已经使用了令人印象深刻的Mediatr Nuget包,它也是Mediator的实现。 So I thought "Why reinvent the Wheel" if I could just use a nice and well tested Mediator. 因此,我想想“为什么要重新发明轮子”,只要我能使用一个经过良好测试的好中介者即可。 But here starts my real Question: In case of sending changes to the global data by other ViewModels to my Readonly ViewModels I would use Notifications. 但这是我真正的问题:如果其他ViewModel将对全局数据的更改发送到我的Readonly ViewModel,我将使用Notifications。 That means: 这意味着:

public class ReadOnlyViewModel : NotificationHandler<Notification>
{
   //some Member

    //global Data
    public string Username {get; private set;}

    public async Task Handle(Notification notification, CancellationToken     token) 
    {
        Username = notification.Username;
    }

}

The Question(s) now: 1. Is this a good Practice for using MVVM (It's just a Feeling that doing this is wrong because it feels like exposing Business Logic in the ViewModel) 2. Is there a better way to seperate this so that my Viewmodel doesn't need to inherit 5 to 6 different NotificationHandlers<,>? 现在的问题:1.这是使用MVVM的一种良好实践(感觉这是错误的,因为感觉就像在ViewModel中公开了业务逻辑一样,这是一种感觉)2.有更好的方法对此进行区分,以便我的Viewmodel不需要继承5到6个不同的NotificationHandlers <,>吗?

Update: As Clarification to what I want to achieve here: My Goal is to implement a wpf application that manages some Global Data (lets say a Username as mentioned above) for one of its Window. 更新:澄清我想在这里实现的目标:我的目标是实现一个wpf应用程序,该应用程序为其窗口之一管理某些全局数据(如上面所说的用户名)。 That means because i am using a DI Container (and because of what kind of data it is) that I have to declare the Service @mm8 proposed as a Singleton. 这意味着因为我使用的是DI容器(并且由于它是哪种数据),所以我必须将提出的Service @ mm8声明为Singleton。 That however is a little bit problematic in case (and I have that case) I need to open a new Window that needs different global data at this time. 但是,在某些情况下(我有这种情况)有点问题,我需要打开一个新窗口,此时需要不同的全局数据。 That would mean that I either need to change the lifetime to something like "kind of scoped" or (breaking the single Responsibility of the class) by adding more fields for different Purposes or I create n Services for the n possible Windows I maybe need to open. 这意味着我要么需要将生存期更改为“某种范围的”,要么(为了打破该类的单一职责),通过为不同目的添加更多字段,或者为n个可能的Windows创建n个服务打开。 To the first Idea of splitting the Service: I would like to because that would mitigate all the above mentioned problems but that would make the sharing of Data problematic because I don't know a reliable way to communicate this global data from the Writeservice to the readservice while something async or parallell running is happening in a Background Thread that could trigger the writeservice to update it's data. 关于拆分服务的第一个想法:我想这样做是因为这样可以缓解上述所有问题,但是这会使数据共享成为问题,因为我不知道将这种全局数据从Writeservice传递到数据库的可靠方法。后台线程中发生异步或并行运行时,可能触发readservice更新其数据。

You could use a shared service that you inject your view models with. 您可以使用注入视图模型的共享服务。 It can for example implement two interfaces, one for write operations and one for read operations only, eg: 例如,它可以实现两个接口,一个用于写操作,一个仅用于读操作,例如:

public interface IReadDataService
{
    object Read();
}

public interface IWriteDataService : IReadDataService
{
    void Write();
}

public class GlobalDataService : IReadDataService, IWriteDataService
{
    public object Read()
    {
        throw new NotImplementedException();
    }

    public void Write()
    {
        throw new NotImplementedException();
    }
}

You would then inject the view models that should have write access with a IWriteDataService (and the other ones with a IReadDataService ): 然后,您应该使用IWriteDataService (和其他具有IReadDataService )的注入应该具有写访问权限的视图模型:

public ViewModel(IWriteDataService dataService) { ... }

This solution both makes the code easy to understand and easy to test. 该解决方案既使代码易于理解又易于测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM