我有一个WPF窗口,其中包含一个包含4个矩形的网格。其中一个有<frame>
用于显示页面,在我的应用程序中使用。我想在窗口和页面上添加命令到这些按钮。
我使用的东西:MVVM,Window as Mainwindow
和Pages as contentpublisher in a frame。
例如,我想使用按钮和命令登录应用程序范围。在我的框架中的页面上执行此操作时没有错误,但我无法在窗口中执行相同的操作。
我想知道窗户是否会失去焦点,因此在导航到框架中的页面时它无法触发该事件。所以我尝试使用以下命令绑定来获取窗口:
<Button Content="" FontFamily="Segoe UI Symbol"
Command="{Binding CommandWhichDoesNotFire, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type vw:MainViewModel}}}"
Width="32">
在我的ViewModel
&#34; MainViewModel&#34;我有一个公共ICommand
属性,我在构造函数中初始化它:
public ICommand CommandWhichDoesNotFire;
public MainViewModel()
{
MessageBox.Show("VM is real");
CommandWhichDoesNotFire= new TestCommand();
}
我的MainView的DataContext
设置在后面的代码之前InitilizeComponents();
单击该按钮不会启动任何调用我的命令。它根本不会发射。我想念的是什么人?
答案 0 :(得分:0)
你应该:
public ICommand CommandWhichDoesNotFire{get;set;}
public MainViewModel()
{
MessageBox.Show("VM is real");
CommandWhichDoesNotFire= new TestCommand(MyCommand);
}
private void MyCommand(object obj){
//Whatever you want to do
}
答案 1 :(得分:0)
我想我找到了解决问题的方法
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中的Command。此时,您必须在代码中分配Window
DataContext
,如下所示:
public MainWindow()
{
InitializeComponent();
var vm = this.TryFindResource("mainVM");
if(vm != null)
{
this.DataContext = vm;
}
}
现在,您可以使用某种触发器浏览网页并使用不同的Page
或UserControl
。 HTH
附:当我有机会时,我将从MSDN更新有关上下文菜单和帧的一些信息。快乐编码