{Binding elementName ...}失败

时间:2017-01-19 00:03:02

标签: c# wpf xaml scope

我用

创建了一个虚拟窗口
  • 一个复选框
  • 一个按钮
  • 自定义UserControl中的按钮

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

我要插入的UserControl:

<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>

2 个答案:

答案 0 :(得分:1)

  

为什么失败

因为UserControl中没有名为“myCheckBox”的CheckBox。父窗口中的CheckBox位于另一个命名范围内,因此绑定到ElementName将不起作用。

  

我怎样才能解决这个问题?

学习并实施MVVM设计模式:https://msdn.microsoft.com/en-us/library/hh848246.aspx。在开发基于XAML的UI应用程序时,它是 推荐的设计模式。

创建保存CheckBox当前状态的视图模型类:

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设置为此实例并绑定到其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>

答案 1 :(得分:0)

您无法从样式中引用myCheckBox,这是两个不同的范围。此外,该样式的目标是一个按钮,但该控件是一个Window。您必须将样式中的所有控件放在控件模板中。