【问题标题】:MVVM WPF change window and close the previousMVVM WPF 更改窗口并关闭上一个
【发布时间】:2016-04-04 10:37:44
【问题描述】:

作为 MVVM 的所有架构的初学者,我对一个窗口到另一个窗口之间的导航有一些疑问。我正在使用框架 MVVM Light。

我期望在 WinForms 中的行为是这样的:

GeneralWindow gw = new GeneralWindow(); this.Hide(); // 或关闭 gw.Show();

我已经浪费了几个小时试图使用信使找到一些提示,但我发现我必须在视图中使用代码隐藏的方法,这不是很 MVVMish。

最好的问候,并在此先感谢您。

【问题讨论】:

    标签: c# wpf mvvm navigation mvvm-light


    【解决方案1】:

    我期望在 WinForms 中的行为是这样的:

    GeneralWindow gw = new GeneralWindow(); this.Hide(); // or close gw.Show();
    

    MVVM 模式将ViewViewModel 分开。所以它没有资格从ViewModel 创建新的View创建窗口实例并从视图模型显示窗口违反了 MVVM"。所以我建议您使用流行的技术,您可以使用 ContentControlDataTemplate 更改 Views

    让我们深入了解这项技术:

    <Window>
       <Window.Resources>
          <DataTemplate DataType="{x:Type ViewModelA}">
             <localControls:ViewAUserControl/>
          </DataTemplate>
          <DataTemplate DataType="{x:Type ViewModelB}">
             <localControls:ViewBUserControl/>
          </DataTemplate>
       <Window.Resources>
      <ContentPresenter Content="{Binding CurrentView}"/>
    </Window>
    

    如果Window.DataContextViewModelA 的实例,则将显示ViewA,而Window.DataContextViewModelB 的实例,则将显示ViewB

    让我举个例子,可以看到应该把DataTemplates放在哪里:

    <Window x:Class="SimpleMVVMExample.ApplicationView"
            ...The code omitted for the brevity...
            Title="Simple MVVM Example with Navigation" Height="350" Width="525">
        <Window.Resources>
           <DataTemplate DataType="{x:Type ViewModelA}">
             <localControls:ViewAUserControl/>
          </DataTemplate>
          <DataTemplate DataType="{x:Type ViewModelB}">
             <localControls:ViewBUserControl/>
          </DataTemplate>
        </Window.Resources>
    
        <DockPanel>
            <Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
                <ItemsControl ItemsSource="{Binding ListOfViewModels}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Button Content="{Binding Name}"
                                    Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                    CommandParameter="{Binding }"
                                    Margin="2,5"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Border>
    
            <ContentControl Content="{Binding CurrentDataTemplateViewModel}" />
        </DockPanel>
    </Window>
    

    我见过和读过的最好的例子是 Rachel Lim 的。 See the example.

    更新:

    如果你想真正打开新窗口,那么你应该创建一个中间层,使ViewModel不依赖于创建新窗口的具体实现。

    public class YourViewModel
    {
        private readonly IWindowFactory windowFactory;
        private ICommand openNewWindow;
    
        public YourViewModel(IWindowFactory _windowFactory)
        {
            windowFactory = windowFactory;
    
            /**
             * Would need to assign value to m_openNewWindow here, and 
             * associate the DoOpenWindow method
             * to the execution of the command.
             * */
            openNewWindow = null;  
        }
    
        public void DoOpenNewWindow()
        {
            windowFactory.CreateNewWindow();
        }
    
        public ICommand OpenNewWindow { get { return 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
    }
    

    如何关闭一个窗口?

    There are a lot of approaches.。其中之一是:

    Application.Current.MainWindow.Close()
    

    【讨论】:

    • 不是视图而是窗口。
    • 感谢您的回答。使用工厂我在关闭上一个窗口时遇到问题,我该怎么做?
    • @Antoine CBreeze 随时提出任何问题。如果您觉得我的回复对您有帮助,那么您可以将我的回复标记为答案,以简化日后其他人的搜索。请阅读此meta.stackexchange.com/questions/5234/…
    猜你喜欢
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 2015-05-28
    • 2016-09-04
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多