TextBox crop behavior WPF/Silverlight

WPF provides an innovative feature called attached properties, which can be used to add behavior to existing controls. These new properties are not defined on the control being extended, but rather they are defined on a separate object (generally a
DependencyObject). Thus, we end up with a source object that defines the attached properties and a target object on which you attach these properties. The target is the object being extended with new functionality contained in the source. When the attached property is set on the target object, a property change event is fired on the source. The event handler is passed information about the target and the new and old values of the property.
By hooking up property changed handlers, we can add additional behavior by calling methods on the target, changing properties, and listening to events. We look at more detailed examples of using attached properties in Chapter 6, “The Power of Attached Properties.” Keep in mind that attached properties are only a means to extend functionality; the original target control still needs to be considered a “black box,” and its internals cannot be modified.

Let’s consider a simple example that illustrates the use of attached properties. Let’s say you want to display a tooltip on the TextBox when the content in the TextBox is exceeded the size of the available size, note that here we are not going to use the TextWrapping on TextBox instead we simply crop the text at the right end and we will display tooltip when user mover mouse on TextBox.

namespace TextBoxCrop
{
public static class TextBoxCropBehavior
{
public static bool GetTextBoxToolTip(DependencyObject obj)
{
return (bool)obj.GetValue(TextBoxCropToolTipProperty);
}
public static void SetTextBoxToolTip(DependencyObject obj, bool value)
{
obj.SetValue(TextBoxCropToolTipProperty, value);
}

public static readonly DependencyProperty TextBoxCropToolTipProperty = DependencyProperty.RegisterAttached(“TextBoxToolTip”, typeof(bool), typeof(TextBoxCropBehavior), new UIPropertyMetadata(false, OnTextCropChanges));
private static void OnTextCropChanges(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textbox = d as TextBox;
if(textbox != null)
{
textbox.SizeChanged += textbox_SizeChanged;
}
else
{
textbox.SizeChanged -= textbox_SizeChanged;
}

}

static void textbox_SizeChanged(object sender, SizeChangedEventArgs e)
{
var textbox = sender as TextBox;
textbox.Measure(new Size(Double.MaxValue, Double.MaxValue));
var width = textbox.DesiredSize.Width;

if (textbox.ActualWidth < width)
{
ToolTipService.SetToolTip(textbox, textbox.Text);
}
else
{
ToolTipService.SetToolTip(textbox, null);
}
}
}
}

And inside XAML attache the behavior to the control like below:

<Window x:Class=”TextBoxCrop.MainWindow”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
Title=”MainWindow” Height=”350″ Width=”525″
xmlns:local=”clr-namespace:TextBoxCrop”>
<Window.Resources>
<Style TargetType=”TextBox”>
<Setter Property=”local:TextBoxCropBehavior.TextBoxToolTip” Value=”True”/>
<Setter Property=”BorderBrush” Value=”Green”/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”*”/>
<ColumnDefinition Width=”*”/>
</Grid.ColumnDefinitions>
<TextBox Text=”Textbox with long text Long text long text long text long text” local:TextBoxCropBehavior.TextBoxToolTip=”True” x:Name=”x” HorizontalAlignment=”Right”/>
</Grid>
</Window>

When you run the application you will see the below UI, notice at the TextBox there is a tooltip on it, it is appearing because the text in the Textbox is exceeded the width limit of available size.

Capture

If your application is having similar requirement in more that one view then you can attach the same behavior to a Textbox style and make it implicit so that it will apply to all the Textbox controls.

Below is the example:

<Window x:Class=”TextBoxCrop.MainWindow”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
Title=”MainWindow” Height=”350″ Width=”525″
xmlns:local=”clr-namespace:TextBoxCrop”>
<Window.Resources>
<Style TargetType=”TextBox”>
<Setter Property=”local:TextBoxCropBehavior.TextBoxToolTip” Value=”True”/>
<Setter Property=”BorderBrush” Value=”Green”/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”*”/>
<ColumnDefinition Width=”*”/>
</Grid.ColumnDefinitions>
<TextBox Text=”Textbox with long text Long text long text long text long text” x:Name=”x” HorizontalAlignment=”Right”/>
</Grid>
</Window>

That’s it 🙂 enjoy coding.

Cheers.