4

できるだけ少ないウィンドウを開くように言っている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ビュー(つまりウィンドウ)にバインドされたViewModelのタイプであり、ラムダctorはウィンドウの新しいインスタンスを返すために使用されます。

このようなウィンドウを管理するのは良い考えですか、それとも私は完全に間違っていますか?

4

2 に答える 2

2

これは悪い考えではなく、実際に私が個人的なプロジェクトで使用したものと同じで、かなりうまく機能します:)

ではWindowManager、画面に表示されているすべての開いているフォームを追跡し、それらの外観と視覚的な関係を管理できます (別のフォームが非表示になっている場合は非表示にするなど)。

于 2012-04-19T09:23:30.000 に答える
2

I think it is a decent idea.

It has the advantage that the ViewModel that wants to show another window doesn't have to use any WPF specific code or even know the view. It only needs to know the ViewModel it wants to show the window for. This is very similar to Caliburn.Micros IWindowManager.

The thing I don't like about this solution is the static nature of the class. This makes unit testing hard(er). If you are using dependency injection, you could create an interface and an implementation of that interface that is similar to your static class. You could then create an instance of that class in your composition root, bind the ViewModel types to the lambda View factories and register that instance with your DI container. Every ViewModel that wants to show another window now has a dependency on that interface which makes it easily mockable in unit tests.

Something like this:

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) { ... }
}

Having the Bind method only on the concrete implementation WindowManager has the benefit that consumers of IWindowManager can't change the registration.

于 2012-04-19T09:19:38.250 に答える