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.

Resize a popup in WPF

Popup control has not build in support for resize. But we can do this by ourself. The following code,

Code Snippet

<Window

   x:Class=”ForumProjects.MainWindow”

   xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

   xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

   Title=”MainWindow” Height=”700″ Width=”800″>

    <StackPanel>

        <Button Click=”ShowPopup”>

            <Grid>

                <TextBlock>Show Popup</TextBlock>

                <Popup Name=”Popup” StaysOpen=”False” Width=”100″ Height=”100″>

                    <Grid Background=”Blue”>

                        <Thumb HorizontalAlignment=”Right”VerticalAlignment=”Bottom” Width=”16″ Height=”16″

                              DragStarted=”onDragStarted”DragDelta=”onDragDelta” DragCompleted=”onDragCompleted”/>

                    </Grid>

                </Popup>

            </Grid>

        </Button>

    </StackPanel>

</Window>

namespace ForumProjects

{

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

        private void ShowPopup(object sender, RoutedEventArgs e)

        {

            this.Popup.IsOpen = true;

        }

        private void onDragStarted(object sender, DragStartedEventArgs e)

        {

            Thumb t = (Thumb)sender;

            t.Cursor = Cursors.Hand;

        }

        private void onDragDelta(object sender, DragDeltaEventArgs e)

        {

            double yadjust = this.Popup.Height + e.VerticalChange;

            double xadjust = this.Popup.Width + e.HorizontalChange;

            if ((xadjust >= 0) && (yadjust >= 0))

            {

                this.Popup.Width = xadjust;

                this.Popup.Height = yadjust;

            }

        }

       private void onDragCompleted(object sender, DragCompletedEventArgs e)

        {

            Thumb t = (Thumb)sender;

            t.Cursor = null;

        }

    }

}

WPF Group Box Style

Recently one of my client asked me to show a good looking group box for our application, so that after a 15 min research i decided to create a group box which will contains a banner at right corner of group box with nice appearance.

I thought it may be useful for others, so i have added this sample in Expression’s Gallery, if you like and wish to use that, download the style and use in your project.

Download Sample project from Here

Sample View:

WPF Group Box

Bullet Decorator in WPF XAML

The BulletDecorator control is used to display a single item and bullet in a bulleted list in WPF. There are many ways to represent the bulleted list in WPF. Following examples are defines different kind of representations.

The BulletDecorator control is used to display a single item and bullet in a bulleted list in WPF. There are many ways to represent the bulleted list in WPF.

Following examples are defines different kind of representations.

<BulletDecorator Margin=”249,109.5,282.167,0″ Height=”23.5″ VerticalAlignment=”Top”>

<BulletDecorator.Bullet>

<Image Source=”ihc_account_24.png” Width=”16″ Height=”16″

VerticalAlignment=”Center”/>

</BulletDecorator.Bullet>

<TextBlock Text=”Image Bullet” Margin=”3.5,0.75,-3.5,3.75″/>

</BulletDecorator>

<BulletDecorator Margin=”249,137,282.167,0″ Height=”23.5″ VerticalAlignment=”Top”>

<BulletDecorator.Bullet>

<Rectangle Fill=”Green” Width=”16″ Height=”16″/>

</BulletDecorator.Bullet>

<TextBlock Text=”Square Bullet” Height=”19″ VerticalAlignment=”Top”

Margin=”3.25,0,-3.25,0″/>

</BulletDecorator>

<BulletDecorator Margin=”249,167,291.167,0″ Height=”23.5″ VerticalAlignment=”Top”>

<BulletDecorator.Bullet>

<Ellipse Fill=”Green” Width=”16″ Height=”16″/>

</BulletDecorator.Bullet>

<TextBlock Text=”Circle Bullet” Height=”19″ VerticalAlignment=”Top”

Margin=”3.25,0,-3.25,0″/>

</BulletDecorator>

<BulletDecorator Margin=”249,197,245.167,0″ Height=”23.5″ VerticalAlignment=”Top”>

<BulletDecorator.Bullet>

<RadioButton Width=”16″ Height=”16″ Margin=”2.5,0,-2.5,0″/>

</BulletDecorator.Bullet>

<TextBlock Text=”Radio Button Bullet” Margin=”4.5,-3.25,-4.5,7.75″/>

</BulletDecorator>

See the below representation

Bullet Decorator Image

Button’s ClickMode property in WPF

The ButtonBase class adds a ClickMode property,which determines when a button fires its Click event in response to mouse actions.

There are three types of click modes in WPF:

  • Release
  • Press
  • Hover

The default value is ClickMode.Release, which means the Click event fires when the mouse is clicked and released. However, you can also choose to fire the Click event mouse when the mouse button is first pressed (ClickMode.Press) or, oddly enough, whenever the mouse moves over the button and pauses there (ClickMode.Hover).

WPF Grid Shared Size Groups

A WPF Grid contains a collection of rows and columns, which are sized explicitly,proportionately, or based on the size of their children. There’s one other way to size a row or a
column—to match the size of another row or column. This works through a feature called shared size groups.

The goal of shared size groups is to keep separate portions of your user interface consistent.For example, you might want to size one column to fit its content and size another column to
match that size exactly. However, the real benefit of shared size groups is to give the same proportions to separate Grid controls.

To understand how this works, consider the example shown in below Figure. This window features two Grid objects—one at the top of the window called Grid 1 (with three columns) and one at the bottom called Grid 2 (with two columns). The second column of the second grid(Grid 2)is linked with the first column of the second column of the first grid(Grid 1), if we resize  the column width of the first grid when the width of the second column also changes accordingly with first grid. The same way with the Hello text’s column.
second Grid stays synchronized.

Shared Grid Size

 <TextBlock Background=”Azure” Margin=”0″ VerticalAlignment=”Bottom”><Run Text=”Grid 1″/></TextBlock>
<Grid Background=”ForestGreen”  ShowGridLines=”True” Margin=”0,-3,0,0″ Grid.Row=”1″>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”Auto” SharedSizeGroup=”ShareThis”/>
<ColumnDefinition Width=”Auto” SharedSizeGroup=”MyCustom” MinWidth=”66.42″/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Width=”Auto” Foreground=”White” x:Name=”SharedTextBlock” Padding=”5″ Background=”#FF5B76AB” Text=”Ravi Srinivas”/>
<TextBlock Padding=”3″ Foreground=”White”  Grid.Column=”1″ Background=”#FFAB9D5B” Text=”Hello”/>
<TextBlock Padding=”3″ Foreground=”White”  Grid.Column=”2″/>
<GridSplitter Grid.Column=”1″
Width=”5″
ShowsPreview=”True” Background=”#FF1D5015″ ToolTip=”Drag me and see the Hello in Second Grid”/>
<GridSplitter Grid.Column=”0″ Width=”5″ Background=”#FF160505″ ToolTip=”Drag me and see the Ravi Srinivas in Second Grid” />
</Grid>
<TextBlock Background=”Azure”  Grid.Row=”2″ Margin=”0,16,0,0″><Run Text=”Grid 2″/></TextBlock>
<Grid Grid.Row=”3″ Background=”ForestGreen”  ShowGridLines=”True”>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”Auto” SharedSizeGroup=”MyCustom”/>
<ColumnDefinition Width=”Auto” SharedSizeGroup=”ShareThis” />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Foreground=”White”  Width=”Auto” x:Name=”SharedTextBlock2″ Background=”#FFAB9D5B” Text=”Hello”/>
<TextBlock Foreground=”White”  Grid.Column=”1″ Background=”#FF5B76AB” Text=”Ravi Srinivas”/>
<GridSplitter Grid.Column=”1″ Width=”5″ Background=”#FF160505″ ToolTip=”Drag me and see the Hello in First Grid” HorizontalAlignment=”Left” Margin=”0″ />
</Grid>

Download the sample here

Design time resources and Attributes in Silverlight/WPF/WP7

When you open a Silverlight/WPF/WP7 application in design mode in Visualstudio or Expression Blend, we may not see the exact look as we expect and see at runtime because of designtime.

There are several reasons for this, major reasons are:

–          Controls are not embedded in a view(Majorly this problem will come if we don’t give width and height)

–          Constructor of a root element is not called.

–          ViewModel is not created

to avoid this you need to provide information to make design view correctly.  You can specify this kind of information by using the design-time attributes.

The designtime attributes are defined in a special namespace, that is usually mapped to the d: prefix. To tell the XAML parser not to interprete these attributes at runtime, the markup compatibility namespace is mapped to mc: and with the mc:Ignorable="d" instruction, the d: namespace is excluded.

EX:

 <UserControl
   xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable="d" />

d:DesignHeight and d:DesignWidth:

The d:designHeight and d:DesignWidth are used to provide fixed height and width at design time.

EX:

<UserControl
    xmlns="http://schemas.microsoft.com/..."
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    d:DesignWidth="640" d:DesignHeight="480" >
<UserControl />

d:LayoutOverrides:

If a property is set to a control at runtime and if we want to change this property at design time we can use the LayoutOverrides.

EX:

<Border Height="250" Width="160" d:LayoutOverrides="Width, Height" >
</Border>

For more information see MSDN