如何使用WPF打开一个关于良好实践的新窗口?

时间:2012-04-19 09:14:39

标签: c# wpf mvvm

我已经阅读了WPF(以及一般的GUI)的一个好习惯,说尽可能少打开窗口。但有时,你根本就没有选择。

所以我想到了一个快速优雅的解决方案,打开一个新窗口,我想到了:

public static class WinManager
{
    private static Dictionary<Type, Func<Window>> collection 
        = new Dictionary<Type, Func<Window>>();

    /* Bind the type of the ViewModel with a lambda that build an 
     * instance of a window*/
    public static void Bind(Func<Window> ctor, Type type) { ... }

    /* Search in the dictionary the specified type and show the window 
     * returned by the lambda*/
    public static void Show(Type type){ ... }

    /* Search in the dictionary the specified type and show the dialogue
     * returned by the lambda*/
    public static void ShowDialog(Type type) { ... }
}

type是绑定到View的ViewModel的类型(即窗口),lambda ctor用于返回窗口的新实例。

管理这样的窗口是个好主意还是我完全错了?

2 个答案:

答案 0 :(得分:2)

我认为这是一个不错的主意。

它的优点是想要显示另一个窗口的ViewModel不必使用任何WPF特定代码,甚至不需要知道视图。它只需要知道它想要显示窗口的ViewModel。这与Caliburn.Micros IWindowManager非常相似。

我不喜欢这个解决方案的是类的静态性质。这使单元测试变得困难(呃)。如果您正在使用依赖项注入,则可以创建一个接口以及与您的静态类类似的该接口的实现。然后,您可以在合成根中创建该类的实例,将ViewModel类型绑定到lambda View工厂,并将该实例注册到DI容器。现在,每个想要显示另一个窗口的ViewModel都依赖于该接口,这使得它在单元测试中很容易模拟。

这样的事情:

interface IWindowManager
{
    void Show(Type type);
    void Show<T>();
    void ShowDialog(Type type);
    void ShowDialog<T>();
}

class WindowManager : IWindowManager
{
    // Implementation of the four methods from the interface plus:

    private Dictionary<Type, Func<Window>> collection 
        = new Dictionary<Type, Func<Window>>();

    public void Bind(Func<Window> ctor, Type type) { ... }
}

仅在具体实施Bind上使用WindowManager方法,有利于IWindowManager的消费者无法更改注册。

答案 1 :(得分:2)

这不是一个坏主意,实际上我在我的个人项目中使用它并且效果很好:)

WindowManager中,您可以跟踪屏幕上可见的所有打开表单,管理它们的外观和视觉关系(隐藏一个,如果另一个也被隐藏,这样的东西)。