代码之家  ›  专栏  ›  技术社区  ›  veljkoz Danko Valkov

WPF使用样式从嵌套元素内绑定到父属性

  •  15
  • veljkoz Danko Valkov  · 技术社区  · 14 年前

    我一直在尝试构建一个文本框,其中包含一个空的提示。 在样式中设置提示文本时遇到问题。

    准确地说,这个 作品 (即正确绑定):

        <TextBox Tag="hint text">
            <TextBox.Background>
                <VisualBrush Stretch="None">
                    <VisualBrush.Visual>
                        <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}" FontStyle="Italic" Foreground="LightGray" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </TextBox.Background>
        </TextBox>
    

    但是,当我将它移到样式时,它不会:

    <Style TargetType="TextBox" x:Key="stlHintbox">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" Value="">
                <Setter Property="Background">
                    <Setter.Value>
                        <VisualBrush Stretch="None">
                            <VisualBrush.Visual>
                                <TextBlock Tag="inner" Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}" 
                                           FontStyle="Italic" Foreground="LightGray" />
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
    
    <TextBox Tag="hint text" Style="{StaticResource stlHintbox}" />
    

    那么有什么收获呢?如何从样式中绑定到祖先属性?

    2 回复  |  直到 14 年前
        1
  •  14
  •   Samuel Jack    14 年前

    问题不在于相对资源,而是在于您使用VisualBrush的方式。回想一下,样式是在应用它们的元素之间共享的。您的示例不起作用的原因是,实际上您正试图与多个父文本框共享一个文本框(标记为“inner”)。

    要了解这是一个问题的原因,请尝试一个思想实验:创建一次内部文本框(大致来说,创建样式时会发生这种情况)。在使用RelativeSource绑定时,应选择应用样式的哪个文本框作为内部文本框的祖先?

    这就是为什么 DataTemplates ControlTemplates 存在于WPF中。它们不是直接实例化视觉对象,而是定义一个模板,允许根据需要创建视觉对象的多个副本。

        2
  •  5
  •   vortexwolf    14 年前

    CreativeSource无法按预期工作。 最好使用控件模板创建水印文本框。但是你的版本可以工作:

    <Window.Resources>
        <Style TargetType="TextBox" x:Key="stlHintbox">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" Value="">
                    <Setter Property="TextBox.Background">
                        <Setter.Value>
                            <VisualBrush Stretch="None" Visual="{Binding ElementName=hintText}"/>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBox Tag="hint text" x:Name="myTextBox" Style="{StaticResource stlHintbox}" />
        <Border Visibility="Hidden">
            <TextBlock x:Name="hintText" Text="{Binding Tag, ElementName=myTextBox}" FontStyle="Italic" Foreground="LightGray" />
        </Border>
    </StackPanel>