{绑定元素名称..} 失败



我创建了一个虚拟窗口

  • 一个复选框
  • a 按钮
  • 自定义用户控件内的按钮

两个按钮都以蓝色开头,选中复选框后,它们都应变为橙色。但是,用户控件中的那个似乎忽略了该复选框。为什么它会失败,我该如何解决这个问题?

我要插入的用户控件:

<UserControl x:Class="UserControl1"
       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"
       mc:Ignorable="d"
       d:DesignHeight="300" d:DesignWidth="300"
       DataContext="{Binding RelativeSource={RelativeSource Self}}"

       <Grid>
            <!--MyContent is a dependency property in UserControl1's code behind-->
            <ContentControl Content="{Binding MyContent}">      
       </Grid>
</UserControl>

主窗口:

<Window x:Class="WpfApplication11.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="350" Width="525">
       <Window.Resources>
           <ResourceDictionary>
               <Style TargetType="Button">
                   <Setter Property="Background" Value="Cyan"/>
                   <Style.Triggers>
                       <DataTrigger Binding="{Binding ElementName=myCheckbox, Path=isChecked}" Value="True">
                           <Setter Property="Background" Value="Orange/>
                       </DataTrigger>
                   </Style.Triggers>
               </Style>
               <Button x:Key="Button1"  Content="Button1"/>
               <Button x:Key="Button2"  Content="Button2"/>
           </ResourceDictionary>
       </Window.Resources>
       <Grid>
           <Grid.RowDefinitions>
               <RowDefinition Height="1*"/>
               <RowDefinition Height="1*"/>
               <RowDefinition Height="1*"/>
           </Grid.RowDefinitions>
           <CheckBox x:Name = "myCheckBox" Content="Turn Orange" Grid.Row="0"/>
           <!--This updates when I check myCheckBox-->        
           <ContentControl Content = "{StaticResource Button1}" Grid.Row="2"/>
           <!--This does NOT update when I check myCheckBox-->
           <test:UserControl1 MyContent="{StaticResource Button2}" Grid.Row="2"/>
       </Grid>
</Window>

为什么会失败

因为用户控件中没有名为"myCheckBox"的复选框。父窗口中的复选框驻留在另一个命名范围内,因此绑定到 ElementName 在此处不起作用。

我该如何解决这个问题?

学习并实现 MVVM 设计模式:https://msdn.microsoft.com/en-us/library/hh848246.aspx。这是开发基于 XAML 的 UI 应用程序时建议使用的设计模式。

创建保存复选框当前状态的视图模型类:

public class ViewModel : INotifyPropertyChanged
{
    private bool _isChecked;
    public bool IsChecked
    {
        get { return _isChecked; }
        set { _isChecked = value; OnPropertyChanged(); }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

并将窗口的 DataContext 设置为 this 的实例,并绑定到其 IsChecked 属性,而不是直接绑定到 CheckBox:

<Window ...>
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Cyan"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsChecked}" Value="True">
                    <Setter Property="Background" Value="Orange"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
        <Button x:Key="Button1"  Content="Button1"/>
        <Button x:Key="Button2"  Content="Button2"/>
    </Window.Resources>
    <Window.DataContext>
        <test:ViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <CheckBox x:Name ="myCheckBox" Content="Turn Orange" Grid.Row="0" IsChecked="{Binding IsChecked}"/>
        <ContentControl Content = "{StaticResource Button1}" Grid.Row="1"/>
        <test:UserControl2 MyContent="{StaticResource Button2}" Grid.Row="2"/>
    </Grid>
</Window>

UserControl 应继承父窗口的 DataContext,因此不要在 UserControl1.xaml 中显式设置 DataContext 属性:

<UserControl x:Class="WpfApplication11.UserControl1"
             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:WpfApplication2"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <ContentControl Content="{Binding MyContent, RelativeSource={RelativeSource AncestorType=UserControl}}" />
    </Grid>
</UserControl>

您不能从样式中引用 myCheckBox,这是两个不同的范围。此外,样式以按钮为目标,但控件是窗口。您必须将所有控件放在控件模板的样式中。

最新更新