我想我已经找到了解决您问题的方法。
Frame 出于某种原因不会继承其父级的 DataContext,即使您像这样明确设置 DataContext:
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"
还是不行。它的作用是只设置框架的DataContext,而不是子元素:
这是子元素的DataContext:
现在这让我想到,我们一直喜欢 WPF 及其控件的任何原因是能够从其父级继承 DataContext,ContextMenu 和现在的 Frame 除外。这是我第一次看到 oyur 问题时采用的方法:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<Window.Resources>
<!--<local:MainVM x:Key="mainVM"/>-->
<local:LoginPage x:Key="login" />
<!--DataContext="{StaticResource mainVM}"-->
<ControlTemplate x:Key="ctrlTmpl">
<local:LoginPage/>
</ControlTemplate>
</Window.Resources>
<Grid>
<!--<Button x:Name="button" Content="Do something" Click="btnDoSomething" HorizontalAlignment="Left" Margin="221,60,0,0" VerticalAlignment="Top" Width="75"/>-->
<!--<Control Template="{StaticResource ctrlTmpl}"/> This works-->
<Frame Content="{StaticResource login}" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" />
</Grid>
然后我想你可以用另一种方式做到这一点:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<!--<Window.DataContext>
<local:MainVM/>
</Window.DataContext>-->
<Window.Resources>
<local:MainVM x:Key="mainVM"/>
<local:LoginPage x:Key="login" DataContext="{StaticResource mainVM}"/>
<!---->
<ControlTemplate x:Key="ctrlTmpl">
<local:LoginPage/>
</ControlTemplate>
</Window.Resources>
<Grid>
<!--<Button x:Name="button" Content="Do something" Click="btnDoSomething" HorizontalAlignment="Left" Margin="221,60,0,0" VerticalAlignment="Top" Width="75"/>-->
<!--<Control Template="{StaticResource ctrlTmpl}"/> This works-->
<Frame Content="{StaticResource login}"/>
</Grid>
请注意我如何将 VM 包含在资源中,然后将该实例用作控件DataContext。此时,当我单击我的 LoginPage.xaml 中的按钮时,顺便说一下 UserControl 它会触发位于我的 MainVM 中的命令。此时,您必须在后面的代码中分配Window DataContext,如下所示:
public MainWindow()
{
InitializeComponent();
var vm = this.TryFindResource("mainVM");
if(vm != null)
{
this.DataContext = vm;
}
}
此时您可以使用某种触发器来浏览页面并使用不同的Pages 或UserControls。 HTH
附言当我有机会时,我会从 MSDN 更新一些关于 Context Menu 和 Frame 的信息。快乐编码