带有参数的 WPF Mvvm 导航
本文关键字:Mvvm 导航 WPF 参数 | 更新日期: 2023-09-27 18:06:06
按照本教程(以及其他内容(并阅读此处提出的问题,我构建了一个导航机制,该机制将允许我在ViewModels
之间传递参数:
对象库 - 每个视图模型都继承自它:
public abstract class ObjectBase : INotifyPropertyChanged
{
//INotifyPropertyChanged members
...
//Navigation handling
public abstract ObjectBase BackLocation { get; }
public abstract event Action<ObjectBase> NavigateTo;
public abstract string ViewHeader { get; }
}
主视图模型 - 负责导航:
public class MainViewModel : ObjectBase
{
private ObjectBase _selectedView;
private CommandBase _backCommand;
public MainViewModel()
{
SelectedView = new FirstViewModel();
}
public ObjectBase SelectedView
{
get { return _selectedView; }
set
{
SetProperty(ref _selectedView, value);
//register to the navigation event of the new view
SelectedView.NavigateTo += (target)=> { SelectedView = target; };
}
}
//This command is bound to a Back button on the main view
public CommandBase BackCommand
{
get { return _backCommand ?? (_backCommand = new CommandBase(Back)); }
}
private void Back(object obj)
{
if (SelectedView.BackLocation != null)
{
SelectedView = SelectedView.BackLocation;
}
else
{
Application.Current.Shutdown();
}
}
}
而主要观点:
<Window ...
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:FirstViewModel}">
<views:FirstView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondViewModel}">
<views:SecondView/>
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding SelectedView}"/>
</Window>
我的问题是:如果我像上面一样在主视图中设置DataTemplates
,它会让每个视图都知道它是DataContext
所以如果我想将DataContext
显式添加到视图中以便像这样使用智能感知:
<UserControl x:Class="Wpf_NavigationTest.Views.FirstView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:Wpf_NavigationTest.ViewModels">
<!--this causes the view model's constructor to get called again-->
<UserControl.DataContext>
<viewModels:FirstViewModel/>
</UserControl.DataContext>
<Grid>
<TextBlock Text="User control 1" FontSize="40"/>
</Grid>
View Model's
构造函数被调用两次,丢失Navigate
事件传递的参数。
这里的问题是您在UserControl
中以及主视图模型中设置DataContext
。
<UserControl.DataContext>
<viewModels:FirstViewModel/>
</UserControl.DataContext>
上面的代码在每次创建此UserControl
时都会实例化一个新FirstViewModel
。因此,当控件由ContentControl
创建(基于DataTemplate
(时,它将继续并创建一个新FirstViewModel
。
因此,这里的解决方案是删除UserControl
中的UserControl.DataContext
声明,您可以改为将ContentControl
的DataContext
设置为SelectedView
的。
<ContentPresenter Content="{Binding SelectedView}"
DataContext="{Binding SelectedView}"/>
为了将多个视图模型用于单个视图,您只需添加另一个DataTemplate
:
<DataTemplate DataType="{x:Type vm:ThirdViewModel}">
<views:SecondView/>
</DataTemplate>
对于设计时数据(获取智能感知(,可以使用本文中所述的d:DataContext
。
这将需要您将一些视图模型设置为静态资源,我建议您在单独的ResourceDictionary
中创建它们。