Wpf 从DataTrigger内绑定子DataContext
我一直在尝试开发一个单选按钮栏(样式为ToggleButtons),用于选择ContentControl中显示的内容。我已经能够使用DataTrigger在ContentControl中显示正确的视图,根据该视图选中RadioButton,但我也尝试将视图模型从父DataContext绑定到子DataContext,但没有成功。最小样本如下所示:Wpf 从DataTrigger内绑定子DataContext,wpf,mvvm,Wpf,Mvvm,我一直在尝试开发一个单选按钮栏(样式为ToggleButtons),用于选择ContentControl中显示的内容。我已经能够使用DataTrigger在ContentControl中显示正确的视图,根据该视图选中RadioButton,但我也尝试将视图模型从父DataContext绑定到子DataContext,但没有成功。最小样本如下所示: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schem
<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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<RadioButton Name="rbShowChild" Content="Show Child" Style="{StaticResource {x:Type ToggleButton}}" />
</StackPanel>
<ContentControl Grid.Row="1">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbShowChild}" Value="True">
<Setter Property="Content">
<Setter.Value>
<local:ChildView DataContext="{Binding ChildViewModel, PresentationTraceSources.TraceLevel=High}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</Window>
var window = new MainWindow()
{
DataContext = new MainWindowViewModel()
};
window.Show();
主窗口DataContext设置如下:
<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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<RadioButton Name="rbShowChild" Content="Show Child" Style="{StaticResource {x:Type ToggleButton}}" />
</StackPanel>
<ContentControl Grid.Row="1">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbShowChild}" Value="True">
<Setter Property="Content">
<Setter.Value>
<local:ChildView DataContext="{Binding ChildViewModel, PresentationTraceSources.TraceLevel=High}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</Window>
var window = new MainWindow()
{
DataContext = new MainWindowViewModel()
};
window.Show();
输出窗口(带有PresentationTraceSources.TraceLevel=High)显示以下内容:
System.Windows.Data Error: 3 : Cannot find element that provides DataContext. BindingExpression:Path=ChildViewModel; DataItem=null; target element is 'ChildView' (Name=''); target property is 'DataContext' (type 'Object')
这让我想到MainWindow.DataContext并不是用来解析触发器中的“{Binding ChildViewModel}”表达式的DataContext,但是我在触发器上找不到任何DataContext属性,在搜索中也找不到任何东西来建议对此的答案
我非常感谢您提出任何解决此问题的建议。更新:问题似乎在于您如何设置数据上下文 在XAML中设置窗口的DataContext,然后将
ContentControl
的数据上下文设置为ChildViewModel
。然后设置实际显示的内容
(又称儿童视图)值
。ContentControl
是此视图的宿主,因此它应该是DataContext
供应商。我自己有点不确定正在进行的确切机制,但我知道下面的代码实际上是有效的
注意,您的XML名称空间可能与下面的代码不同。相应地调整
<Window.DataContext>
<!-- Data Context added here OR in code-behind initialize-->
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<RadioButton Name="rbShowChild" Content="Show Child" Style="{StaticResource {x:Type ToggleButton}}" />
</StackPanel>
<!-- Bind the ContentControls Data context-->
<ContentControl DataContext="{Binding ChildViewModel}" Grid.Row="1">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbShowChild}" Value="True">
<Setter Property="Content">
<Setter.Value>
<!-- Just simply set the view content here, no binding.-->
<local:ChildView />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
这样做,我已经在一个项目中很好地运行了您的应用程序。谢谢您的回复,Toskr。我尝试了这两种方法,但我认为这并不能解决我的问题。MainWindowDataContext似乎工作正常,即使在原始项目中也是如此。未设置的是ChildView数据上下文。当您在这些更改后说它对您有效时,您是在单击按钮时看到绑定的文本字符串“it works!”还是仅看到字符串“Child”(未绑定,只是在XAML中)?触发器正在显示子视图,只是没有设置子DataContext。我看到显示字符串“It works”。也许可以发布有关如何以及在何处设置数据上下文的信息。创建主窗口并设置其数据上下文的原始代码位于App.OnStartup()中。我还将您建议的更改添加到MainWindow构造函数和XAML中。我不知道为什么它对你有效,但对我无效。此外,如果我将它添加到我的主窗口中,它会在那里显示“它有效!”,这同样意味着我的主窗口DataContext设置正确。从App.OnStartup设置主窗口DataContext时,如果不在您建议的任何位置重新设置,它对您是否有效?我要到早上才会在电脑前,所以我会深入研究。然而,这感觉可能是其中一种情况,在这种情况下,您可能忽略了一些导致事情无法按预期工作的小错误。我建议你仔细检查一下。例如,您是否在子视图代码隐藏中执行了任何操作?在运行时有任何可能破坏孩子绑定的内容吗?也许是你忘了移除的东西?