简体   繁体   English

MVVM共享属性

[英]MVVM shared properties

There are some similar questions on SO, but they weren't quiet the same, so I'm posting this instead. 在SO上也有一些类似的问题,但是它们并没有完全相同,因此我将其发布了。 I'm new to MVVM, so I'm trying to figure out how I can create a class that can hold properties that can be shared among views. 我是MVVM的新手,所以我试图弄清楚如何创建一个可以容纳可以在视图之间共享的属性的类。 So, if I set a property in one view, all the other views would get notified if its changed and would adjust their properties accordingly. 因此,如果我在一个视图中设置了一个属性,则所有其他视图的更改都会得到通知,并会相应地调整其属性。

What I have now is rather very crude and is definitely not something I want to use. 我现在所拥有的非常粗糙,绝对不是我要使用的东西。 This is my common class that will hold all the properties: 这是我的通用类,它将包含所有属性:

public static class Common
{
    private static string _title;
    public static string Title
    {
        get { return _title; }
        set
        {
            if (_title == value)
            {
                return;
            }

            _title = value;
            OnPropertyChanged("Title");
        }
    }

    public static void Load()
    {
        // set properties here
    }

    public static event PropertyChangedEventHandler PropertyChanged;

    private static void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(typeof(SettingsWorker), new PropertyChangedEventArgs(name));
        }
    }
}

...and I have to subscribe to it from each ViewModel: ...并且我必须从每个ViewModel订阅它:

Common.PropertyChanged += Common_PropertyChanged;

private void Common_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Title = Common.Title;
}

But this is where the breakdown happens. 但这是发生故障的地方。 I can get the property name from the PropertyChangedEventArgs , but I've no idea how to get the value. 我可以从PropertyChangedEventArgs获取属性名称,但是我不知道如何获取该值。 Therefore, I'm forced to update all the properties, and that can get nasty to maintain. 因此,我被迫更新所有属性,而这会使维护变得很讨厌。 The code is becoming a mess. 代码变得一团糟。

I'm basically trying to get properties that ViewModels can share. 我基本上是在尝试获取ViewModels可以共享的属性。 How can I accomplish this? 我该怎么做?

It looks like you just have some global data you want to show in multiple places. 看起来您只是想在多个位置显示一些全局数据。 The most straightforward way to do this is to just make it like and normal ViewModel class and then make it available to each of your other ViewModels and expose it from them to bind to directly (rather than copying the property into each of them). 最简单的方法是使其与普通的ViewModel类相似,然后使其可用于其他ViewModel,并将其公开以直接绑定(而不是将属性复制到每个ViewModel中)。 You can do this using IOC, or make it available statically, more similar to how you have it now. 您可以使用IOC进行此操作,也可以使其静态可用,这与您现在拥有的方式更相似。

If you go the static direction, the key change you need to make is to use a singleton rather than a static class in order to allow property change notification to work. 如果您沿静态方向发展,则需要进行的关键更改是使用单例而不是静态类,以允许属性更改通知起作用。 Bindings work with INPC on instances but not static classes. 绑定在实例上使用INPC,但不能在静态类上使用。 The Common class would look more like this: Common类看起来像这样:

public class Common : INotifyPropertyChanged
{
    private static Common _instance = null;

    protected Common()
    {
    }

    public static Common GetInstance()
    {
        if (_instance == null)
            _instance = new Common();

        return _instance;
    }

    private string _title;
    public string Title
    {
        get { return _title; }
        set
        {
            if (_title == value)
                return;
            _title = value;
            OnPropertyChanged("Title");
        }
    }

    public void Load()
    {
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
        if (PropertyChanged != null)
            PropertyChanged(this, ea);
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

There are a lot of different ways you can then use this. 然后,您可以使用多种不同的方式来使用它。 Here's one of the more direct ones: 这是更直接的一种:

public class SomeViewModel : ViewModelBase
{
    public Common CommonData { get; private set; }

    public SomeViewModel()
    {
        CommonData = Common.GetInstance();
    }
}

Then in XAML you can bind to the properties from the common class and get change notification, even across the different VM usages. 然后,在XAML中,您甚至可以跨越不同的VM使用情况,也可以绑定到公共类的属性并获取更改通知。

<TextBox Text="{Binding Path=CommonData.Title}"/>

There's also the option of making the singleton accessible as a property and binding to it directly from XAML using x:Static but that's a little different direction that what you were asking. 还可以选择将单例作为属性进行访问,并使用x:Static从XAML直接绑定到单例,但这与您要问的方向略有不同。

So if you have other views that want to get notified when a property changes I would assume you have a separate viewmodel for each of those views. 因此,如果您有其他想要在属性更改时得到通知的视图,我将假定您为每个视图都拥有一个单独的视图模型。 In that case what you would be asking for is "How can viewmodels talk to other viewmodels?" 在这种情况下,您要问的是“视图模型如何与其他视图模型对话?” For a good learning experience, I would recommend looking into the observer pattern. 为了获得良好的学习体验,我建议您研究观察者模式。 If you don't like that style, then I would recommend you look into using a MVVM Framework like "SimpleMVVM, Catel, or many others" (Just need to look some up). 如果您不喜欢这种样式,那么我建议您考虑使用MVVM框架,例如“ SimpleMVVM,Catel或许多其他样式”(只需查找一下)。 Then once you have that framework in you project, I would create a baseviewmodel class that all your viewmodels will inherit. 然后,在项目中拥有该框架后,我将创建一个所有视图模型都将继承的baseviewmodel类。 Once that is done you can take advantage of the frameworks messenger system. 一旦完成,您就可以利用框架信使系统。 Basically it would look something like: 基本上看起来像这样:

    public YourViewModel()
    {           
        RegisterToReceiveMessages(MessageTokens.SomeToken, OnChangeCallYourMethodToAddress); //The MessageTokens is something you generally create ur self.
    }

    #region Notifications
    void OnChangeCallYourMethodToAddress(object sender, NotificationEventArgs<SlideShowLocale> e)
    {
        SomeProperty = e.Data;
    }

Then to send a message to "YourViewModel" From another ViewModel: 然后将消息从另一个ViewModel发送到“ YourViewModel”:

    public AnotherViewModel
    {
        SendMessage(MessageTokens.SomeToken, new NotificationEventArgs(WhateverYouWantToSend));
    }

So basically, by declaring the token you want, it then finds the viewmodel that is registered with that token and listens for any messages to come in. 因此,基本上,通过声明所需的令牌,然后它找到使用该令牌注册的视图模型,并侦听任何传入的消息。

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

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