Guillaume
Guillaume

Reputation: 1244

TextBox TextTrimming

I would like to apply a TextTrimming option on a TextBox (Not a TextBlock).

The compiler tells me that the TextTrimming options is not a valid property of the Textbox.

I could do a fancy control that is a Textblock and once it's clicked will become a Textbox and conversely go back to being a Textblock once the focus is lost.

Before going this way I would like to know if a built-in function already exists (or is there a smarter way) to allow you to do that?

EDIT: What I want to have in the end is a TextBox which is trim (the full content will be display in a tooltip) but when the user select the TextBox (enter in "edit mode") the full content will be display (without trim) therefore the user will be able to modify the full text. when the TextBox lost the focus (go back to "view mode") the content will be trim again.

Thanks

Upvotes: 27

Views: 32572

Answers (5)

Nicholas Miller
Nicholas Miller

Reputation: 4400

Dan Puzey has a great answer, but I wanted to add more so that the style of the TextBlock appeared like a TextBox.

Here is the XAML style I came up with:

<Style TargetType="TextBox">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="False">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <Border BorderThickness="1" CornerRadius="1">
                            <Border.BorderBrush>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FFABADB3" Offset="0"/>
                                    <GradientStop Color="#FFABADB3" Offset="0.044"/>
                                    <GradientStop Color="#FFE2E3EA" Offset="0.060"/>
                                    <GradientStop Color="#FFE3E9EF" Offset="1"/>
                                </LinearGradientBrush>
                            </Border.BorderBrush>
                            <TextBlock Padding="4,2,0,0" Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

This is what the control looks like when it has no keyboard focus:

TextBlock - No Keyboard Focus

This is what the control looks like after gaining keyboard focus:

TextBox - With Keyboard Focus

Upvotes: 3

Mr.B
Mr.B

Reputation: 3787

enter image description here

enter image description here

I would use different control template: template with trimming when text box is not focused, whereas text box is focused I would use the regular template to allow text selection. Needs to replace TextBox control template.

 <ControlTemplate TargetType="{x:Type TextBox}"
                 x:Key="ControlTemplateTextBoxNormal">
    <Border Background="{TemplateBinding Background}"
            BorderThickness="{TemplateBinding BorderThickness}"
            BorderBrush="{TemplateBinding BorderBrush}">
        <Grid>
            <Border x:Name="ErrorElement"
                    Visibility="Collapsed"
                    BorderThickness="1.25"
                    BorderBrush="{StaticResource BrushError}">
                <Grid>
                    <Polygon x:Name="toolTipCorner"
                             Panel.ZIndex="2"
                             Margin="-1"
                             Points="9,9 9,0 0,0"
                             Fill="{StaticResource BrushError}"
                             HorizontalAlignment="Right"
                             VerticalAlignment="Top">
                        <Polygon.ToolTip>
                            <ToolTip Style="{StaticResource ToolTipStyleError}"
                                     Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
                        </Polygon.ToolTip>
                    </Polygon>
                </Grid>
            </Border>
            <ScrollViewer x:Name="PART_ContentHost"
                          Padding="{TemplateBinding Padding}"
                          BorderThickness="0"
                          IsTabStop="False"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                          TextElement.Foreground="{TemplateBinding Foreground}" />
            <TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
                       IsHitTestVisible="False"
                       Visibility="Collapsed"
                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                       Margin="{TemplateBinding Padding}"
                       Foreground="Gray"
                       x:Name="watermark" />
        </Grid>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsFocused"
                 Value="False">
            <Setter Property="Visibility"
                    TargetName="watermark"
                    Value="Visible" />
        </Trigger>
        <Trigger Property="Validation.HasError"
                 Value="True">
            <Setter Property="Visibility"
                    TargetName="ErrorElement"
                    Value="Visible" />
        </Trigger>
        <!--<Trigger Property="behaviors:TextBoxBehaviors.WatermarkText"
                             Value="True">
                        <Setter Property="Visibility"
                                TargetName="ErrorElement"
                                Value="Visible" />
                    </Trigger>-->

    </ControlTemplate.Triggers>
</ControlTemplate>
 <Style TargetType="{x:Type TextBox}"
       BasedOn="{StaticResource {x:Type TextBox}}"
       x:Key="TextBoxStyleTrimming">
    <Setter Property="BorderThickness"
            Value="1" />
    <Setter Property="Validation.ErrorTemplate"
            Value="{x:Null}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Border Background="{TemplateBinding Background}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}">
                    <Grid>
                        <Border x:Name="ErrorElement"
                                Visibility="Collapsed"
                                BorderThickness="1.25"
                                BorderBrush="{StaticResource BrushError}">
                            <Grid>
                                <Polygon x:Name="toolTipCorner"
                                         Panel.ZIndex="2"
                                         Margin="-1"
                                         Points="9,9 9,0 0,0"
                                         Fill="{StaticResource BrushError}"
                                         HorizontalAlignment="Right"
                                         VerticalAlignment="Top">
                                    <Polygon.ToolTip>
                                        <ToolTip Style="{StaticResource ToolTipStyleError}"
                                                 Content="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" />
                                    </Polygon.ToolTip>
                                </Polygon>
                            </Grid>
                        </Border>
                        <TextBlock Padding="{TemplateBinding Padding}"
                                   Text="{TemplateBinding Text}"
                                   TextTrimming="CharacterEllipsis"
                                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                   VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                   TextElement.Foreground="{TemplateBinding Foreground}" />
                        <TextBlock Text="{Binding Path=(behaviors:TextBoxBehaviors.WatermarkText), RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"
                                   IsHitTestVisible="False"
                                   Visibility="Collapsed"
                                   HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                   VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                   Margin="{TemplateBinding Padding}"
                                   Foreground="Gray"
                                   x:Name="watermark" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsFocused"
                             Value="False">
                        <Setter Property="Visibility"
                                TargetName="watermark"
                                Value="Visible" />
                    </Trigger>
                    <Trigger Property="Validation.HasError"
                             Value="True">
                        <Setter Property="Visibility"
                                TargetName="ErrorElement"
                                Value="Visible" />
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsKeyboardFocused"
                 Value="True">
            <Setter Property="Template"
                    Value="{StaticResource ControlTemplateTextBoxNormal}" />
        </Trigger>
    </Style.Triggers>
</Style>

Upvotes: 2

Dan Puzey
Dan Puzey

Reputation: 34200

Try a style like this (I've added background colours to make the change obvious):

    <Style TargetType="TextBox">
      <Setter Property="Background" Value="Yellow" />
      <Style.Triggers>
        <DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="TextBox">
                <TextBlock Text="{TemplateBinding Text}"  TextTrimming="CharacterEllipsis" Background="Red" />
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </DataTrigger>
      </Style.Triggers>
    </Style>

Upvotes: 49

Nicolas Repiquet
Nicolas Repiquet

Reputation: 9265

You may create a control template for your TextBox that display the usual editor when focused, and a TextBlock with trimming when it's not.

Upvotes: 0

Akanksha Gaur
Akanksha Gaur

Reputation: 2686

I think wat you are looking for is this

<TextBox Text="{Binding Path=String, Converter={StaticResource StringConverter}, ConverterParameter=Trim:Argument:AnotherArgument}" /> 

I hope it helps :)

It will call the trim function and pass any arguments, if you want. You can also use split and pass the delimiters as arguments.

You can find more on Binding.Converter here

Upvotes: 0

Related Questions