WPF Привязка к родительскому свойству из вложенного элемента с использованием стиля - PullRequest
15 голосов
/ 04 сентября 2010

Я пытался создать текстовое поле с подсказкой, которая отображается, пока она пуста. У меня проблемы с настройкой текста подсказки из стиля.

Если быть точным, то это работает (то есть оно правильно связывается):

    <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 голосов
/ 07 сентября 2010

Проблема не в RelativeSource, а в том, как вы используете VisualBrush.Напомним, что стили совместно используются элементами, к которым вы их применяете.Причина, по которой ваш пример не работает, заключается в том, что, по сути, вы пытаетесь разделить одно текстовое поле (помеченное как «внутреннее») с несколькими родительскими текстовыми полями.

Чтобы понять, почему это проблема, попробуйте мысленный эксперимент: внутреннее текстовое поле создается один раз (грубо говоря, это произойдет при создании стиля).Какие из текстовых полей, к которым применяется стиль, следует выбрать в качестве предка внутреннего текстового поля при использовании привязки RelativeSource?

Именно поэтому DataTemplates и ControlTemplates существует в WPF.Вместо непосредственного создания экземпляров визуалов они определяют шаблон, который позволяет создавать несколько копий визуалов по мере необходимости.

5 голосов
/ 04 сентября 2010

Reativesource не работает должным образом.Лучше создать текстовое поле водяного знака, используя шаблон управления.Но ваша версия может работать:

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