WPF从用户控件MVVM更改视图

3

我想要在没有任何侧边栏的情况下从一个视图模型导航到另一个视图模型。

例如,我有一个主窗口视图,这是我加载用户控件的地方。

我尝试从MainViewModel访问静态实例以更改视图,但它不起作用。

MainWindow.xaml

<Window.Resources>

    <DataTemplate DataType="{x:Type vm:FirstViewModel}">
        <v:FirstView/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type vm:SecondViewModel}">
        <v:SecondView/>
    </DataTemplate>

</Window.Resources>
<ContentControl Content="{Binding CurrentViewModel}"/>

MainViewModel.cs

class MainviewModel : ObservableObject
{
    private ObservableObject _currentViewModel = new FirstViewModel();
    public ObservableObject CurrentViewModel
    {
        get { return _currentViewModel; }
        set
        {
            _currentViewModel = value;
            RaisePropertyChangedEvent("CurrentViewModel");
        }
    }

    private static MainViewModel _instance = new MainViewModel();
    public static MainViewModel Instance { get { return _instance; } }
}

这里有我的FirstView,它只包含一个按钮和几个其他的UI设计

FirstView.xaml

<Button Command="{Binding goToSecondView}" />

FirstViewModel.cs

class FirstViewModel : ObservableObject
{
    public ICommand goToSecondView
    {
        get
        {
            return new DelegateCommand(() =>
            {
                MainViewModel.Instance.CurrentViewModel = new SecondViewModel();
            });
        }
    }
}

我有一个名为SecondView的视图,它与FirstView类似,只是导航到FirstView
我已经尝试搜索解决方案,但迄今为止,我只找到了一些示例,显示在面板上的按钮可以通过单击这些按钮来切换User Control
我想要实现的是通过User Control本身上的按钮来启用User Control的切换,而不需要任何侧面板。
非常感谢任何帮助,并肯定会在我的未来项目中使用。

不要自己管理这个。Caliburn.Micro等人已经非常好地完成了这项工作。https://github.com/Caliburn-Micro/Caliburn.Micro - MoonKnight
2
来吧,@Killercam,你不需要安装整个框架来完成这个任务。 - Sheridan
但是,Sheriden,它在哪里结束呢?显然,这可以在没有它的情况下完成,但是Caliburn相对较轻,并且对于WPF/MVVM的新手来说,您很快就会意识到不使用MVVM框架可能会很繁琐/艰难。 - MoonKnight
你如何设置MainWindowDataContext?你尝试订阅它的PropertyChanged事件,以查看它是否实际上是静态实例了吗? - Sjeijoet
我可能会看一下那个框架,@Killercam。谢谢你的建议。 - Manuel J
2个回答

2

您正在创建两个不同的MainViewModel实例。第一个可能是由定位器或其他东西创建的,并且在窗口首次创建时绑定到视图。然后它创建了第二个实例并将其分配给自己的静态Instance成员:

private static MainViewModel _instance = new MainViewModel();
public static MainViewModel Instance { get { return _instance; } }

当你按下按钮时,你的ICommand处理程序正在更改此实例,但它未绑定到任何内容。一般来说,您应该使用依赖注入框架来确保它是真正的单例,但现在只需执行以下操作:

    public MainViewModel()
    {
        Instance = this;
    }

    public static MainViewModel Instance { get; private set; }

你的代码中调用了RaisePropertyChangedEvent("CurrentViewModel"),我相信你的意思应该是RaisePropertyChanged("CurrentViewModel")。

非常感谢您的回答。它非常详细,帮助我理解了我做错的地方。我将听从您的建议并研究依赖注入框架,我一直在努力提高自己的知识水平。 - Manuel J

0
我会选择另一种方式,从您的第一个和第二个视图模型中公开一个事件,例如:
public event EventHandler<ShowMeEventArgs> ShowMeEvent;

然后你的主函数只需订阅此事件并显示viewmodel。而且你的第一个和第二个viewmodel甚至不需要了解mainviewmodel中的任何内容


嗨@blindmeis,我该如何公开一个事件?我对C#还比较新,非常渴望学习。如果您能提供一个简单的示例,那就太好了。当然,我也尝试过寻找有关如何公开事件的解决方案,只是不知道如何将它们应用到我的项目中。 - Manuel J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接