从DataTrigger中绑定子DataContext

时间:2017-04-22 05:31:44

标签: wpf mvvm

我一直在尝试开发一个RadioButtons条(设置为ToggleButtons),它选择在ContentControl中显示哪些内容。我已经能够使用DataTrigger根据检查的RadioButton在ContentControl中显示正确的视图,但我也尝试将父模型DataContext中的视图模型绑定到子的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>

绑定到ChildViewModel似乎是没有按预期工作的部分。为了完整性,这里是相关的ChildView。

<UserControl x:Class="WpfApplication1.ChildView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <StackPanel>
            <TextBlock Text="Child" />
            <TextBlock Text="{Binding Text}" />
        </StackPanel>
    </Grid>
</UserControl>

ViewModels:

namespace WpfApplication1
{
    public class ChildViewModel
    {
        public string Text { get; set; }

        public ChildViewModel()
        {
            Text = "It works!";
        }
    }

    public class MainWindowViewModel
    {
        public ChildViewModel ChildViewModel { get; set; }

        public MainWindowViewModel()
        {
            ChildViewModel = new ChildViewModel();
        }
    }
}

MainWindow DataContext设置如下:

        var window = new MainWindow()
        {
            DataContext = new MainWindowViewModel()
        };
        window.Show();

“输出”窗口(使用PresentationTraceSources.TraceLevel =“高”)显示:

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属性,也没有能够在我的搜索中找到任何建议来为此提供答案。

我非常感谢有任何解决此问题的建议。

1 个答案:

答案 0 :(得分:0)

更新:看起来问题在于如何设置数据上下文。

在XAML中设置窗口的DataContext,然后将ContentControl的数据上下文设置为ChildViewModel。然后设置实际显示的Content(AKA ChildView)ValueContentControl是此视图的主持人,因此它应该是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>

这样做,我已经在项目中运行了你的应用程序。