Home > other >  XAML Binding Parent field to a Child value from ResourceDictionnary
XAML Binding Parent field to a Child value from ResourceDictionnary

Time:01-04

I made a style to create a TextBox with a Placeholder.

<Style TargetType="TextBox" x:Key="PlaceholderTextBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Border Background="White" BorderBrush="Black" BorderThickness="1">
                        <Grid>
                            <TextBox VerticalAlignment="Stretch"
                                     VerticalContentAlignment="Stretch"
                                     x:Name="MessageBox"
                                     Background="Transparent"
                                     TextWrapping="Wrap"
                                     BorderThickness="0"
                                     Margin="2,0,0,0"
                                     Text="{Binding Message, Mode=TwoWay, 
                                     UpdateSourceTrigger=PropertyChanged}">
                            </TextBox>

                            <TextBlock IsHitTestVisible="False"
                                       Text="{TemplateBinding Tag}"
                                       VerticalAlignment="Center"
                                       HorizontalAlignment="Left"
                                       Margin="4,0,0,0"
                                       Foreground="Gray"
                                       FontStyle="Italic">
                                <TextBlock.Style>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="Visibility" Value="Collapsed" />
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Text,
                                            ElementName=MessageBox}" Value="">
                                                <Setter Property="Visibility" Value="Visible" />
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

It works well, but when I want to access the data from my TextBox, I can't get it to retrieve the data.

<StackPanel Orientation="Horizontal">
    <Label Content="Filtre : " />
    <TextBox x:Name="TxtFiltre" Width="120" Height="16" Margin="4,0,4,0"
    KeyUp="TxtFiltre_KeyUp" Style="{StaticResource PlaceholderTextBox}"
    Tag="Search" />
</StackPanel>

I tried to bind the Text value from the TextBox and the TextBlock in style, but none worked.

In debug I saw that the value entered in my TextBox can be found on the Text element, but the source is ParentTemplate and not Default. I don't understand the difference and if it has something to do with the style and not being able to retrieve the data.

CodePudding user response:

If you want to re template the textbox then you need to start with a viable textbox template.

I wasn't particularly careful with what follows so consider this an illustration rather than bullet proof cut and paste.

It uses the background brush for the watermark.

<Window.Resources>
    <Style TargetType="{x:Type TextBox}" x:Key="WatermarkTextBoxStyle">
        <Setter Property="SnapsToDevicePixels"
      Value="True" />
        <Setter Property="OverridesDefaultStyle"
      Value="True" />
        <Setter Property="KeyboardNavigation.TabNavigation"
      Value="None" />
        <Setter Property="FocusVisualStyle"
      Value="{x:Null}" />
        <Setter Property="MinWidth"
      Value="120" />
        <Setter Property="MinHeight"
      Value="20" />
        <Setter Property="AllowDrop"
      Value="true" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border Name="Border"
                    CornerRadius="2"
                    Padding="2"
                    BorderThickness="1">
                        <Border.Background>
                            <VisualBrush Stretch="None"
                     AlignmentX="Left">
                                <VisualBrush.Visual>
                                    <TextBlock FontSize="12" 
                                         Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}"
                                         Foreground="LightGray" >
                                        <TextBlock.Style>
                                            <Style TargetType="TextBlock">
                                                <Setter Property="Opacity" Value="0"/>
                                                <Style.Triggers>
                                                    <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
                                                        <Setter Property="Opacity" Value="1"/>
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="True">
                                                        <Setter Property="Opacity" Value="0"/>
                                                    </DataTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </TextBlock.Style>
                                    </TextBlock>
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Border.Background>
                        <Border.BorderBrush>
                            <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                        </Border.BorderBrush>
                        <ScrollViewer Margin="0"  x:Name="PART_ContentHost" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<StackPanel>
    <TextBox Style="{StaticResource WatermarkTextBoxStyle}"
             Tag="Watermark Text"/>

A markup in place version might be clearer. There's not a huge amount to this. I set the opacity to zero if the textbox has focus ( so the user is about to start typing ) or the text is not "". Meaning they typed something in.

    <TextBox>
        <TextBox.Background>
                <VisualBrush Stretch="None"
                             AlignmentX="Left">
                    <VisualBrush.Visual>
                        <TextBlock FontSize="12" 
                            Text="Watermark Text"
                            Foreground="LightGray" >
                            <TextBlock.Style>
                                <Style TargetType="TextBlock">
                                    <Setter Property="Opacity" Value="0"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource  AncestorType=TextBox}}" Value="">
                                            <Setter Property="Opacity" Value="1"/>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource  AncestorType=TextBox}}" Value="True">
                                            <Setter Property="Opacity" Value="0"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBlock.Style>
                        </TextBlock>
                    </VisualBrush.Visual>
                </VisualBrush>
        </TextBox.Background>
    </TextBox>
  • Related