XAML 用MVVM(.Net6)管理WPF项目中视图的最佳方法是什么

gcmastyq  于 2023-08-01  发布在  .NET
关注(0)|答案(1)|浏览(101)

首先,如果我的问题看起来“简单”,我道歉。
我必须将一个使用.Net Framework 4.5.2设计的旧WPF项目升级到.Net 6(还有一些其他改进)。
从.Net Framework 4.5.2到.Net 6的迁移已经完成,并且运行得非常好。
但是,在旧项目中,有一个带有菜单的MainView,每个菜单项都使用ShowDialog()打开一个新窗口。在这些新窗口中,还可以使用ShowDialog()等打开其他窗口。
因此,您最终可能会打开四个窗口,但由于ShowDialog(),前三个窗口被冻结(let it go,let it go,sorry XD)。您必须关闭第四个窗口,然后是第三个,然后是第二个,然后才能到达主窗口。
看上去真的很乱。
我想通过只有一个活动/可见的窗口而不重写整个项目来改善这种情况。
当前,MainView(MainView.xaml.cs)使用以下代码打开一个新窗口:

var v = new MyNewView();
v.Owner = this;
v.ShowDialog();

字符串
在这个新视图中,您将获得具有以下内容的视图模型:

public MyNewView()
{
        DataContext = ViewModelLocator.GetViewModelInstance<ModelContext, MyNewViewModel>(this);
        InitializeComponent();
}


(ModelContext是DBContext)
ViewModelLocator是这样的:

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        Ioc.Default.ConfigureServices(
            new ServiceCollection()
            .AddSingleton<ApplicationContext>()
            .AddTransient<MainViewModel>()
            .AddTransient<MyNewViewModel>()
            .BuildServiceProvider());
    }

    public static Tvm GetViewModelInstance<TContext, Tvm>(ICloseableEvent w, bool initializeContext = true) where Tvm : IDisposable where TContext : ModelContext
    {
        Tvm VMInstance = Ioc.Default.GetService<Tvm>();
        if (initializeContext)
            (VMInstance as CommonViewModel<TContext>)!.InitializeContext();
        w.Closed += (sender, args) =>
        {
            WeakReferenceMessenger.Default.UnregisterAll(VMInstance);
            VMInstance.Dispose();
        };
        return VMInstance;
    }
}


我找到的解决方案是在MainView.xaml中定义一个ContentControl,如下所示:

<ContentControl x:Name="MainContent"/>


然后,我没有用“ShowDialog”打开一个新窗口,而是简单地用MyNewView的内容替换MainView的内容,就像这样(在MainView.xaml.cs中):

MyNewView myNewView = new MyNewView();
myNewView.Owner = App.MainView;

App.MainView.MainContent.Content = myNewView.Content;
App.MainView.Title = myNewView.Title;

myNewView.Close();


如果我关闭“MyNewView”,我只需使用MainView的内容重置MainContent。它工作(但我不确定这是否是一个好的解决方案)。但是,视图模型没有改变。视图仍然寻找MainViewModel而不是MyNewViewModel,即使“DataContext = ViewModelLocator.GetViewModelInstance<ModelContext,MyNewViewModel>(this);”正确调用。
所以,我不认为这是一个很好的解决方案,毕竟。
在WPF应用程序中从一个视图导航到另一个视图的最佳方法是什么(在.Net 6中使用MVVM)?

  • 是否将Window转换为UserControl更好(MainView除外)?
  • 是否有更好的方法来调用视图?

请让我知道如果你需要更多的细节,请理解,因为我是相当新的WPF,我只是想做正确的方式。
提前感谢!

enyaitl3

enyaitl31#

多亏了@Andy,我找到了一些可能的解决方案。
我没有试图解释我是如何做到的,而是创建了一个我所阐述的解决方案的示例项目。
左侧菜单有意消失以显示导航级别(子->父)。
https://github.com/damgot/WpfMvvmNavigationSample

相关问题