Showing posts with label Custom Controls. Show all posts
Showing posts with label Custom Controls. Show all posts

Tuesday, May 19, 2009

WatermarkTextBox by inheriting TextBox

I am very happy to see that my previous post “WPF Watermark TextBox using XAML Style” helped a lot of peoples to solve their issues and currently that is the most popular post in my blog.That post describes about creating a WPF watermark textbox by changing it’s style.All the things are done in xaml and there is no property to set the water mark text.
There was a requirement from one of the readers for such a property.ie a Watermark property which decides the watermark text.So rewriting the sample with that property.
Here I just derived a new class called WatemarkTextBox from standard TextBox added a new dependency property called Watermark and defined default style for that control in generic.xaml.The steps are as follows

  1. Subclass TextBox and create a new class called WatermarkTextBox.
  2. Add a new DP called Watermark which is of type object.
  3. In the generic.xaml write the default style.
public class WatermarkTextBox : TextBox
{
static WatermarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox),
new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
}

public object Watermark
{
get { return (object)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
// Using a DependencyProperty as the backing store for Watermark. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
"Watermark",
typeof(object),
typeof(WatermarkTextBox),
new UIPropertyMetadata(null));
}

And its style in generic.xaml contains almost same elements as of my last post.But here I have used TemplateBinding to set Watermark into the TextBlock.

<Style TargetType="{x:Type local:WatermarkTextBox}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderBrush"
Value="Blue" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Padding"
Value="1" />
<Setter Property="AllowDrop"
Value="true" />
<Setter Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:WatermarkTextBox}">
<Grid>
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd"
SnapsToDevicePixels="true"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
RenderFocused="{TemplateBinding IsKeyboardFocusWithin}"
RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Microsoft_Windows_Themes:ListBoxChrome>
<TextBlock x:Name="textBlock"
Opacity="0.345"
Text="{TemplateBinding Watermark}"
TextWrapping="Wrap"
Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Visibility"
TargetName="textBlock"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Download sample from here.

Monday, September 24, 2007

More WPF custom control design time experience in Expression blend

Custom category editors
This is a continuation to my older post which described about custom property editors in blend.This post mainly discuss about creating a custom category editor and putting properties into that.
Here I am using more design specific mechanism with separate design time dlls, which was introduced with WPF technology.It helps us to keep our design time code in a separate dll which is suffixed with <assemblyname>.design.dll.You can get more information about the linking process between Control dll and design dll from here .
.


We are going to create a category named MyCategory like this

Steps

  1. Create metadata file in the design assembly ie in <customasembly>.design.dll
  2. Put the desired property into appropriate category using the category attribute.This is same as of Windows forms
  3. Create category editor and set its datatemplate.
  4. Use the editor attribute to associate this category editor into the custom control
  5. Open the solution in Blend.You can see your category editor

The new category with full customization

Some points to consider

  • Make sure that the design dll and application(which is using our custom control) is refering the same custom control assembly dll.Otherwise this wont get opened in blend.

For more details refer the sample here









Monday, September 17, 2007

Writing code behind for generic.xaml

Have you ever thought of a method which allows you to write code behind for your generic.xaml ?

If you fed up searching for such an option,here is the solution with 3 simple steps...

  1. Add a file named generic.xaml.cs
    • Right click on themes folder and select new class
    • Name it as generic.xaml.cs
  2. Change the definition of the class inside generic.xaml.cs as
    partial class generic :ResourceDictionary //This class should inherit from ResourceDictionary
  3. Link this code behind file to Gereric.xaml by using x:Class

    <ResourceDictionary
    x:Class="MyControls.themes.generic"
    //The class name should be complete.ie with namespace

Now you can write code for your generic.xaml elements in the generic.xaml.cs file.

The same method can be applied if you want to write code behind for any other xaml resource file.

A sample is attached here

Wednesday, June 27, 2007

Extending HeaderedItemsControl to have Footer !!!

The normal HeaderedContentControl in WPF gives us the facility to have a header up on the ItemsControl.This will be enough in most of the cases.But if you are looking for a ItemsControl which needs Footer too this is your solution.


  1. Solution 1

Use the Tag Property to hold Content of Footer.And Template it to have Footer.No inheritance!!!



<HeaderedItemsControl>
<HeaderedItemsControl.Header>Header</HeaderedItemsControl.Header>
<TextBlock Text="Item1" Background="LightGray"/>
<TextBlock Text="Item2" Background="LightGray"/>
<TextBlock Text="Item3" Background="LightGray"/>
<HeaderedItemsControl.Tag>Header</HeaderedItemsControl.Tag>
<HeaderedItemsControl.Template>
<ControlTemplate TargetType="{x:Type HeaderedItemsControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height ="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentPresenter ContentSource="Header" Grid.Row="0"/>
<ItemsPresenter Grid.Row="1" />
<ContentPresenter ContentSource="Tag" Grid.Row="2"/>
</Grid>
</Border>
</ControlTemplate>
</HeaderedItemsControl.Template>
</HeaderedItemsControl>

Thursday, June 21, 2007

How to specify which property of my custom class should take the Content from xaml?

Use System.Windows.Markup.ContentProperty attribut on the class
Eg:
If you are creating a custom class for clock control and wanna Time to take the Content from xaml use as follows.

[System.Windows.Markup.ContentProperty("Time")]
public class Clock : Control {
public DateTime Time{
}
}

Hence the xaml looks like

<MyControl:Clock >
4:30:34
</MyControl:Clock >

Thursday, May 17, 2007

Creating Custom property editors for Blend & Orcas

Explaining how to create custom property editors for Blend & Orcas using WPF features.

Requirements
  • A latest version of Blend.Preferably May 2007 CTP
  • Microsoft's new design dll .This is in .net3.5.You may also use this with 3.0.

I am taking famous Clock control from codeproject and implementing the custom property editor

Steps

  1. Get the sample from code project.
  2. Open the sample and make a reference to new design dll.If you already have orcas 1(3.5) it would be in your machine.Else download from here.
  3. Prepare the DataTemplate of the property editor.Better save in the generic.xaml file itself.An eg given below


    <DataTemplate x:Key="TimeEditorDataTemplate">
    <Grid>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>>
    <TextBox Text="{Binding Path=Value, Mode=TwoWay}"/>
    <PropertyEditing:EditModeSwitchButton Grid.Column="1" Content="Change"/>
    </Grid>
    </DataTemplate>

  4. Create our own editor by inheriting from Microsoft.Windows.Design.PropertyEditing.DialogPropertyValueEditor
  5. Set the DataTemplates..See the below code

    public class TimeEditor : Microsoft.Windows.Design.PropertyEditing.DialogPropertyValueEditor {

    public TimeEditor(): base() {
    //This is to get the DataTemplate of editor from generic.xaml file Uri

    resourceLocator = new Uri("MyControls" + @";component/themes/generic.xaml", UriKind.RelativeOrAbsolute);
    ResourceDictionary rd = (ResourceDictionary)Application.LoadComponent(resourceLocator);
    DataTemplate dt = rd["TimeEditorDataTemplate"] as DataTemplate;
    this.InlineEditorTemplate = dt;
    this.DialogEditorTemplate = dt; } }

  6. Now set the editor into desired property


    [Editor(typeof(TimeEditor), typeof(DialogPropertyValueEditor))]
    public DateTime MyTime {
    get{ return (DateTime) GetValue(MyTimeProperty); }
    set{ SetValue(MyTimeProperty, value); }
    }

  7. Yes.Thats it.Instantiate your control in Blend and see the PROPERTYEDITOR

Download full sample here

Its a great design time experience with designers (Visusl studio ExpressionBlend). Right?

More details

http://blogs.msdn.com/jnak/archive/2007/08/10/adding-design-time-metadata-to-cider-and-blend.aspx