Search code examples
c#wpfviewmodelbind

Bind Textbox Text with style from template to a viewmodel


I have some textbox whith style from a template like this

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Border Background="White" CornerRadius="8" x:Name="container">
                        <Grid>
                            <TextBox Background="White"
                                     FontFamily="Poppins" FontSize="11"
                                     VerticalAlignment="Center"
                                     Padding="5"
                                     Name="SearchBox"
                                     Foreground="Black"
                                     Margin="2"
                                     BorderThickness="0"
                                     Text="{TemplateBinding Text}"
                                    />

                            <TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
                                       FontSize="11" FontFamily="Poppins"
                                       Foreground="Gray"
                                       VerticalAlignment="Center"
                                       IsHitTestVisible="False"
                                       Grid.Column="1" Padding="5" Margin="6,0,0,0">

                                <TextBlock.Style>
                                    <Style TargetType="{x:Type TextBlock}">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
                                                <Setter Property="Visibility" Value="Visible"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>
                                        <Setter Property="Visibility" Value="Hidden"></Setter>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </Grid>

                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Just to show an placeholder. This works but something goes wrong when I try to bind property Text to a view model.

                        <TextBox Text="{Binding NombreCliente}" 
                         Style="{StaticResource SearchTextBox}"
                         Grid.Row="1"
                             Tag="Nombre"/>

I've done test and while the textbox have this style the binding always return null or "". I find in other ask that there's something whith binding parent and they solve whith this

  <TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, 
  UpdateSourceTrigger=PropertyChanged}"....

But if i bind text to a template parent, how do I bind to viewmodel?


Solution

  • A template of a TextBox should not contain another TextBox control.

    Replace it with a ScrollViewer and set the FontFamily and FontSize properties using Style setters:

    <ControlTemplate TargetType="{x:Type TextBox}">
        <Border Background="White" CornerRadius="8" x:Name="container">
            <Grid>
                <ScrollViewer x:Name="PART_ContentHost" Margin="2" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
    
                <TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
                                           FontSize="11" FontFamily="Poppins"
                                           Foreground="Gray"
                                           VerticalAlignment="Center"
                                           IsHitTestVisible="False"
                                           Grid.Column="1" Padding="5" Margin="6,0,0,0">
    
                    <TextBlock.Style>
                        <Style TargetType="{x:Type TextBlock}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
                                    <Setter Property="Visibility" Value="Visible"></Setter>
                                </DataTrigger>
                            </Style.Triggers>
                            <Setter Property="Visibility" Value="Hidden"></Setter>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </Grid>
    
        </Border>
    
        <ControlTemplate.Triggers>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>