我已经阅读了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
用于返回窗口的新实例。
管理这样的窗口是个好主意还是我完全错了?
答案 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
中,您可以跟踪屏幕上可见的所有打开表单,管理它们的外观和视觉关系(隐藏一个,如果另一个也被隐藏,这样的东西)。