【问题标题】:Where to place global variables in MVVM (Caliburn micro)在 MVVM 中放置全局变量的位置(Caliburn micro)
【发布时间】:2013-10-26 01:22:08
【问题描述】:

我正在将在 WinForms 中完成的程序重构为 WPF,并使用 Caliburn.Micro 作为框架来实现 MVVM 模式。

在旧程序中,我使用StatisHelper 类来允许不同的静态变量,如主题、语言、用户名或访问权限等。

我知道这可能是不安全的,因为这些变量是公开的,但我怀疑我的最终用户知道如何访问这些值...

无论如何,我想知道 MVVM 中保存全局值的最佳实践(具体来说,我使用的是 Caliburn.Micro 框架),所有视图模型都可以访问这些值。

感谢您的回复。

【问题讨论】:

标签: c# wpf mvvm caliburn.micro


【解决方案1】:

您可以使用单例类(有些人不赞成)。注意构造函数是private,所以没有其他东西可以创建实例。使用Instance 属性来访问它。本例中的Instance 属性只会在第一次访问时构造单例对象。

要使用它,只需执行var foo = Globals.Instance.SomeProperty 之类的操作。

请注意,这与 WPF 或 MVVM 无关,也可以在 WinForms 中使用。

public class Globals {
    private Globals _Instance;
    public Globals Instance {
        get {
            if (_Instance == null)
                _Instance = new Globals();
            return _Instance;
        }
    }

    private Globals() {
    }

    public string SomeProperty { get; set; }
}

【讨论】:

  • Globals.Instance.SomeProperty 无法调用。实例需要用“静态”定义。例如。私有静态全局_instance;和公共静态全局实例{ get{...} }
  • 请像@alex 提到的那样将静态添加到代码中。像这样 Singleton 的成员无法访问!
【解决方案2】:

我使用了一个自定义的StateManager 类,它实现了Singleton 模式,因此应用程序中只有这些实例之一:

public class StateManager : INotifyPropertyChanged
{
    private static StateManager instance = new StateManager();

    /// <summary>
    /// Initialises a new empty StateManager object.
    /// </summary>
    public StateManager() { }

    /// <summary>
    /// Gets the single available instance of the application StateManager object.
    /// </summary>
    public StateManager Instance
    {
        get { return instance; }
    }

    ...
}

然后在我的基本视图模型中引用它,以便我的所有视图模型都可以访问它:

public StateManager StateManager
{
    get { return stateManager.Instance; }
}

此外,因为它在我的视图模型类中被引用,我也可以Bind 到 XAML 中的值:

<Window Title="{Binding StateManager.WindowTitle, Mode=OneWay}" ... />

【讨论】:

    【解决方案3】:

    嗯,我的回答是结合了@Steve 和@Sheridan 的想法以及评论中的链接。

    首先,我不得不说将数据和代码分开。

    至于数据,我会使用那些 Resx 文件来存储所有这些类型的资源,无论它们是二进制资源,如简单的音频文件、图像、可本地化的字符串等......,因为这可以在运行时轻松交换它们。

    至于代码,我会使用像 IConfigurationProvider 这样的集合:

    public interface IConfigurationProvider {
    
        GetResourceByName<T>(string key); // T is the type of the requested resource
    
        // THIS IS A SIMPLIFIED VERSION, YOU CAN HAVE MORE METHODS
        // ACCORDING TO YOUR NEEDS 
    
    }
    

    此接口的实现可以使用 Resx 文件来存储和检索资源,然后您可以将这些资源注入到需要它的不同类中。

    这有一些优点,例如:

    • 更好的可测试性
    • 可以在不改变界面的情况下使用不同的媒体来存储资源数据
    • 在运行时交换实现,您现在可以使用 DI。
    • 更清楚数据来自哪里

    【讨论】:

    • 对不起@Sniffer,我是编码新手(我正在尽我最大的努力),所以,你能详细说明一下吗?给您带来的不便深表歉意。谢谢。
    • @OscarMateu 您需要更具体一些,您对什么感到困惑?这个主题值得单独写一篇文章。
    • 嗨@Sniffer,我必须在哪里使用这个界面?在 MainWindowViewModel 中?我有一个有多个屏幕的活动导体,每个都有它的视图模型。
    • @OscarMateu 您可以在需要从资源中提取信息的任何地方使用它。通常在我的应用程序中,我有一个配置屏幕,您可以在其中设置应用程序选项并在那里使用它。
    猜你喜欢
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多