Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

c# - Open a new Window in MVVM

Lets say I have a MainWindow and a MainViewModel, I'm not using MVVM Light or Prism in this example.
In this MainWindow I want to click a MenuItem or Button to open a NewWindow.xaml not a UserControl.
I know how to use this with UserControl to open a new UserControl in my existing Window in a ContrntControl or a Frame.

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

Code

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

In the ResourceDitionary for MainWindow I have :

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

The thing is that I want to open a new Window, not a UserControl. So I use some code like this :

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();
}

and then a bind OpenNewWindow to a MenuItem or Button.
I know this is not the right way, but what is the right way to do this ?

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are two problems you need to solve with this type of application.

Firstly, you do not want to have the View-Model creating and displaying UI components directly. One of the motivations for using MVVM is to introduce test-ability in to your View-Model, and having this class pop up new windows makes this class harder to test.

The second problem you need to solve is how to resolve the dependencies in your application, or in this instance – how to you “hook up” the View-Model to the corresponding View? A maintainable solution to this latter problem is given by the use of a DI container. A very good reference to this subject is given by Mark Seemann’s Dependency Injection in .NET. He actually also discusses how to solve the first problem too!

To solve the former problem, you need to introduce a layer of indirection to your code, to make the View-Model not dependent on a concrete implementation of creating a new window. A very simple example is given in the code below:

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
}

Note that you take an implementation of IWindowFactory in the constructor of your View-Model, and it is to this object that the creation of the new window is delegated to. This allows you to substitute the production implementation for a different one during testing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...