15

假设我有 aMainWindow和 a ,在这个例子中MainViewModel我没有使用MVVM LightPrism 。
在此MainWindow我想单击 aMenuItemButton打开 a NewWindow.xamlnot a UserControl
我知道如何使用它来在我现有的 Window 中UserControl打开一个新的 a或 a 。UserControlContrntControlFrame

<ContentControl Content="{Binding Path=DisplayUserControl,UpdateSourceTrigger=PropertyChanged}" />

代码

public ViewModelBase DisplayUserControl
{
    get
    {
        if (displayUserControl == null)
        {
            displayUserControl = new ViewModels.UC1iewModel();
        }
        return displayUserControl;
    }
    set
    {
        if (displayUserControl == value)
        {
            return;
        }
        else
        {
            displayUserControl = value;
            OnPropertyChanged("DisplayUserControl");
        }
    }
}

在我有ResourceDitionaryMainWindow

<DataTemplate DataType="{x:Type localViewModels:UC1ViewModel}">
    <localViews:UC1 />
</DataTemplate>
<DataTemplate DataType="{x:Type localViewModels:UC2ViewModel}">
    <localViews:UC2 />
</DataTemplate>

问题是我想开一个新的Window,而不是一个UserControl。所以我使用这样的代码:

private ICommand openNewWindow;

public ICommand OpenNewWindow
{
    get { return openNewWindow; }
}

public void DoOpenNewWindow()
{
    View.NewWindowWindow validationWindow = new View.NewWindow();
    NewWindowViewModel newWindowViewModel = new NewWindowViewModel();
    newWindow.DataContext = ewWindowViewModel;
    newWindow.Show();
}

然后绑定OpenNewWindow到 a MenuItemor Button
我知道这不是正确的方法,但是正确的方法是什么?

谢谢!

4

1 回答 1

28

这种类型的应用程序需要解决两个问题。

首先,您不希望 View-Model 直接创建和显示 UI 组件。使用 MVVM 的动机之一是在 View-Model 中引入测试能力,让这个类弹出新窗口会使这个类更难测试。

您需要解决的第二个问题是如何解决应用程序中的依赖关系,或者在这种情况下——如何将 View-Model “连接”到相应的 View?后一个问题的可维护解决方案是通过使用 DI 容器给出的。Mark Seemann 的.NET 中的 Dependency Injection对此主题提供了很好的参考。他实际上也讨论了如何解决第一个问题!

要解决前一个问题,您需要在代码中引入一层间接层,以使 View-Model 不依赖于创建新窗口的具体实现。下面的代码给出了一个非常简单的例子:

public class ViewModel
{
    private readonly IWindowFactory m_windowFactory;
    private ICommand m_openNewWindow;

    public ViewModel(IWindowFactory windowFactory)
    {
        m_windowFactory = windowFactory;

        /**
         * Would need to assign value to m_openNewWindow here, and associate the DoOpenWindow method
         * to the execution of the command.
         * */
        m_openNewWindow = null;  
    }

    public void DoOpenNewWindow()
    {
        m_windowFactory.CreateNewWindow();
    }

    public ICommand OpenNewWindow { get { return m_openNewWindow; } }
}

public interface IWindowFactory
{
    void CreateNewWindow();
}

public class ProductionWindowFactory: IWindowFactory
{

    #region Implementation of INewWindowFactory

    public void CreateNewWindow()
    {
       NewWindow window = new NewWindow
           {
               DataContext = new NewWindowViewModel()
           };
       window.Show();
    }

    #endregion
}

请注意,您IWindowFactory在 View-Model 的构造函数中实现了 ,并且新窗口的创建被委托给该对象。这允许您在测试期间将生产实现替换为不同的实现。

于 2013-05-20T15:35:14.780 回答