Category Archives: WPF

Caliburn Micro and inversion of control using Ninject

Caliburn Micro comes with it’s own built in mechanism for creating objects as and when required. However it’s bootstrapper comes with methods which allow us to override the default behaviour. The methods such as GetInstance, GetAllInstances and BuildUp are used to resolve dependencies in a user supplied IoC container.

I’m the built in mechanism is more than adequate for most peoples usage, but I tend to rather like Ninject. So here are the steps (which ofcourse can be used with your own preferred IoC framework).

Create a bootstrapper as per the following (where ShellViewModel is replaced with your view model name)

public class AppBootstrapper : Bootstrapper<ShellViewModel>
{
   protected override void Configure()
   {
   }

   protected override void OnExit(object sender, EventArgs e)
   {
   }

   protected override object GetInstance(Type service, string key)
   {
   }

   protected override IEnumerable<object> GetAllInstances(Type service)
   {
   }

   protected override void BuildUp(object instance)
   {
   }
}

These are the methods we need to override and implement the code for, to allow Caliburn Micro to use our preferred Ioc framework.

Configure

The configure method is used to configure Caliburn Micro to use our IoC framework, so basically this is where we instantiate the StandardKernel in Ninject. Firstly add a class level variable as follows

private IKernel kernel;

Next override the Configure method to both create the kernel and set-up default bindings

protected override void Configure()
{
   kernel = new StandardKernel();

   kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
   kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
}

We’re going to want to have access to the WindowManager and EventAggregator within our code, so we’ll set up the bindings for them. If we’re passing a class to the generic argument of the Bootstrapper this this is enough code for the Configure method, but if, as I often prefer, we have something like

public class AppBootstrapper : Bootstrapper<IShellViewModel>

i.e. an interface passed as the generic argument, then we need to also set up the bindings within Ninject to resolve this interface. Hence adding the line

kernel.Bind<IShellViewModel>().To<ShellViewModel>().InSingletonScope();

to the end of the Configure method.

OnExit

Now we’ve created the instance of the kernel, the OnExit method allows us to place cleanup code such as

protected override void OnExit(object sender, EventArgs e)
{
   kernel.Dispose();
   base.OnExit(sender, e);
}

This is (as you can see from the arguments, a event handler that Caliburn Micro hooks up to the Application.Exit event.

GetInstance

This must be overridden when providing our own IoC container. The method is used get the service for a given service, so we can simply call the following

protected override object GetInstance(Type service, string key)
{
   if (service == null)
      throw new ArgumentNullException("service");

   return kernel.Get(service);
}

GetAllInstances

This method must be overridden when supplying our own IoC container and is used to get all instances of a service. We can override it thus

protected override IEnumerable<object> GetAllInstances(Type service)
{
   return kernel.GetAll(service);
}

BuildUp

Finally, and again required when supplying our own IoC container, we need to override the BuildUp method. This is used inject instances into the IoC container and can be written as

protected override void BuildUp(object instance)
{
   kernel.Inject(instance);
}

Full Code

The full code for this is as follows

public class AppBootstrapper : Bootstrapper<ShellViewModel>
{
   private IKernel kernel;

   protected override void Configure()
   {
      kernel = new StandardKernel();

      kernel.Bind<IWindowManager>().To<MetroWindowManager>().InSingletonScope();
      kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();

      kernel.Bind<IShellViewModel>().To<ShellViewModel>().InSingletonScope();
   }

   protected override void OnExit(object sender, EventArgs e)
   {
      kernel.Dispose();
      base.OnExit(sender, e);
   }

   protected override object GetInstance(Type service, string key)
   {
      if (service == null)
         throw new ArgumentNullException("service");
			
      return kernel.Get(service);
   }

   protected override IEnumerable<object> GetAllInstances(Type service)
   {
      return kernel.GetAll(service);
   }

   protected override void BuildUp(object instance)
   {
      kernel.Inject(instance);
   }
}

Beginning with Caliburn Micro

Let’s take a look at some of the basics of Caliburn Micro.

Let’s start with the bare minimum, skeleton app to get us started…

  1. Create a WPF application is Visual Studio
  2. Use NuGet to add Caliburn.Micro via the references context menu
  3. Open App.xaml and remove the StartupUri=”MainWindow.xaml”
  4. Delete the file MainWindow.xaml as Caliburn Micro will create the main window for our application
  5. Caliburn Micro uses naming convention to allow it to load the relevant view for the view model, so the view should be prefixed with the same name as the viewmodel, i.e. create a class named ShellViewModel which will become the entry point to the application. Then create a UserControl named ShelllView
  6. Open ShellViewModel and drived the class from PropertyChangedBase (ass the using clause for Caliburn.Micro).

    PropertyChangedBase gives us the implementation of INotifyPropertyChanged for the databinding. So the code should look like

    public class ShellViewModel : PropertyChangedBase
    {
    }
    

    Obviously don’t forget to add Caliburn.Micro as a using clause

  7. Open the ShellView.xaml file and (just so we can easily see the user control’s usage, change the Background to a colour of your choosing. Also changed the Width and Height to a sensible starting value otherwise the application will open just as the caption bar. The user control size gives the initial size of the main window when it’s displayed
  8. Now we need to create the code to actually create the main window and hook display our intial control. Create a new class, it can be named anything you like but I’ll named mine AppBootstrapper to fit in with the App.xaml name
  9. Derive AppBootstrapper from Bootstrapper as per
    public class AppBootstrapper : Bootstrapper<ShellViewModel>
    {
    }
    

    Obviously don’t forget to add Caliburn.Micro as a using clause.

    As you’ll see we set the Bootstrapper up with the view model, not the view. Caliburn Micro’s naming conventions will work out the view name as ShellView and handle the composition of the views from this.

  10. At this point we have all the bits for Caliburn Micro to work but we need to actually get the bootstrapper to load. The simplest way is to edit App.xaml and enter the following code between the Application.Resources

    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary>
    <local:AppBootstrapper x:Key="bootstrapper" />
    </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

    Obviously added the namespace as required.

Now if you run this you should see an application window with the dimensions based upon the size of the ShellView control and if you chose a different colour background this should be displayed.

The WPF ListView

By default a ListView looks and acts much like a standard WPF ListBox (when in it’s default state) but ofcourse we can also include headers/columns and groupings whichon top of the basic list of data.

Let’s assume we’re wanting to display a collection of Person objects where the Person type is made up of FirstName, LastName and Age. For this example assume these are exposed by the People property on our view model.

To display our collection we can simply do the following

<ListView ItemsSource="{Binding People}" />

But this will display the type name for each item in our collection and ofcourse doesn’t have headings. So to add headings we need to use the following

<ListView ItemsSource="{Binding People}">
   <ListView.View>
      <GridView>
         <GridViewColumn Header="First Name" Width="150" 
                   DisplayMemberBinding="{Binding FirstName}"/>
         <GridViewColumn Header="Last Name" Width="150" 
                   DisplayMemberBinding="{Binding LastName}"/>
         <GridViewColumn Header="Age" Width="100" 
                   DisplayMemberBinding="{Binding Age}"/>
      </GridView>
   </ListView.View>
</ListView>

this will also display the members we’re binding to so no longer display the type name.

So far so good, but to add groupings we need to do a little more work. In XAML we have the following (in the Window ResourceDictionary)

<CollectionViewSource Source="{Binding People}" x:Key="GroupedItems">
   <CollectionViewSource.GroupDescriptions>
      <PropertyGroupDescription PropertyName="LastName" />
   </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

If using the above XAML we also need to alter the ListView’s ItemSource to this

<ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}">

this will then bind to the GroupedItems. Note we must use the “Source=” XAML.

We can also easily declare the same groupings in C# code as per below

CollectionView collectionView = 
      (CollectionView)CollectionViewSource.GetDefaultView(list.ItemsSource);
PropertyGroupDescription pgd = new PropertyGroupDescription("LastName");
collectionView.GroupDescriptions.Add(pgd);

Note: in the above case our ListView has the x:Name=”list” and ofcourse doesn’t require the ItemsSource binding change listed for the XAML code.

Using the CollectionView we add property group descriptions but we need to amend our ListView XAML to use this. By adding the ListView.GroupStyle as per below, we create the control template for the groupings

<ListView.GroupStyle>
   <GroupStyle>
      <GroupStyle.ContainerStyle>
         <Style TargetType="GroupItem">
            <Setter Property="Template">
               <Setter.Value>
                  <ControlTemplate TargetType="{x:Type GroupItem}">
                     <StackPanel>
                        <TextBlock FontWeight="Bold" 
                                FontSize="14" Text="{Binding Path=Name}"/>
                        <ItemsPresenter/>
                     </StackPanel>
                  </ControlTemplate>
               </Setter.Value>
            </Setter>
         </Style>
      </GroupStyle.ContainerStyle>
   </GroupStyle>
</ListView.GroupStyle>

The key things to note in the above XAML are that we need to ensure we put the ItemsPresenter into the ControlTemplate or now items are displayed and we do not bind to the data but instead bind to the CollectionViewGroup which is what the CollectionViewSource groups the data into. So in this case Name represents the string data for the grouping name and we could also bind to ItemCount for example if we wanted to show to the user the number of items in the grouping.

A simple lookless control in WPF

One of the key design principles for designing controls in WPF is the separation of UI from the actual control implementation (or functionality if you prefer). The aim is to create a control with properties, methods, events, states etc. as needed that does not rely on the specifics of the way the UI displays the control.

I’m going to work through a very simple lookless control to just get an idea how such a control might be implemented.

What’s the control going to be ?

Okay I don’t want anything too large as this is mean’t as a quick and easy to follow post. So the control will be a countdown timer control. A control which takes a time, in seconds and each second decreases the count until it reaches zero at which point it stops.

The control will have the following properties

From – this will hold to countdown “from” value (in seconds). In other words the value we start the countdown at.
Current – this will hold the current value in the countdown, obviously this will reduce from the “From” value down to zero.
IsRunning – this will allow us to know if the countdown timer is running.

Steps

  1. Create a CountdownControl class and implement the properties described above
  2. Create a CountdownControl XAML file and create a default style
  3. Create an alternate UI by overriding the ControlTemplate

Let’s implement this thing

Step 1

So step 1 is to create a new class called CountdownControl, we will derive this from a Control as we’re not looking to extend any existing control for this. So it should look like

public class CountdownControl : Control
{
}

Nothing exciting there.

As we’re going to countdown from a given value and for this example we’ve assumed the use of seconds only. We’ll use the DispatcherTimer to give us an event every second which will allow us to decrement the current value accordingly. As this isn’t mean’t to be a step by step for coding this I’ll simply point out that we can use the snippets in Visual Studio 2012 (dp and dpp) to create the propeties as follows.

  1. Create the IsRunning as a dependency property with property changed event
  2. Create the CurrentProperty as a readonly dependency property
  3. Create the From as a dependency property with property changed event
  4. Create a CountdownControl constructor and add the code to created the timer
  5. create the timer tick event and have it decrement the Current property until it reaches 0 then set the IsRunning to false
  6. On the OnIsRunningRunningChanged either start or stop the timer depending on the value passed to it
  7. On the OnFromChanged, set the IsRunning to true if a value greater than 0 is assigned to the From property

And here’s the code

public class CountdownControl : Control
{
   private readonly DispatcherTimer timer;

   public CountdownControl()
   {
      timer = new DispatcherTimer();
      timer.Interval = TimeSpan.FromSeconds(1);
      timer.Tick += TimerTick;
   }

   private void TimerTick(object sender, EventArgs e)
   {
      if (Current > 0)
      {
         SetValue(CurrentPropertyKey, Current - 1);
         if (Current == 0)
         {
            IsRunning = false;
         }
      }
   }

   public static readonly DependencyProperty IsRunningProperty =
		DependencyProperty.Register("IsRunning", typeof(bool), 
                typeof(CountdownControl),
		new FrameworkPropertyMetadata((bool)false,
		new PropertyChangedCallback(OnIsRunningChanged)));

   public bool IsRunning
   {
      get { return (bool)GetValue(IsRunningProperty); }
      set { SetValue(IsRunningProperty, value); }
   }

   private static void OnIsRunningChanged(DependencyObject d, 
               DependencyPropertyChangedEventArgs e)
   {
      CountdownControl target = (CountdownControl)d;
      bool oldIsRunning = (bool)e.OldValue;
      bool newIsRunning = target.IsRunning;
      target.OnIsRunningChanged(oldIsRunning, newIsRunning);
   }

   protected virtual void OnIsRunningChanged(bool oldIsRunning, bool newIsRunning)
   {
      if (!DesignerProperties.GetIsInDesignMode(this))
      {
         if (newIsRunning)
            timer.Start();
         else
            timer.Stop();
      }
   }

   private static readonly DependencyPropertyKey CurrentPropertyKey
		= DependencyProperty.RegisterReadOnly("Current", typeof(int), 
                        typeof(CountdownControl),
			new FrameworkPropertyMetadata((int)0));

   public static readonly DependencyProperty CurrentProperty
		= CurrentPropertyKey.DependencyProperty;

   public int Current
   {
      get { return (int)GetValue(CurrentProperty); }
   }

   public static readonly DependencyProperty FromProperty =
		DependencyProperty.Register("From", typeof(int), typeof(CountdownControl),
		new FrameworkPropertyMetadata((int)0,
		new PropertyChangedCallback(OnFromChanged)));

   public int From
   {
      get { return (int)GetValue(FromProperty); }
      set { SetValue(FromProperty, value); }
   }

   private static void OnFromChanged(DependencyObject d, 
                 DependencyPropertyChangedEventArgs e)
   {
      CountdownControl target = (CountdownControl)d;
      int oldFrom = (int)e.OldValue;
      int newFrom = target.From;
      target.OnFromChanged(oldFrom, newFrom);
   }

   protected virtual void OnFromChanged(int oldFrom, int newFrom)
   {
      SetValue(CurrentPropertyKey, newFrom); 
      IsRunning = (newFrom > 0);
   }
}

As can be seen, there’s no UI code here, only properties and functionality yet this will implement a countdown clock.

Note: The user of the DesignerProperties.GetIsInDesignMode is to stop the control counting down when in the XAML designer

Before we move onto the next step, which is to add a default style/look, let’s finish up here by creating the following static constructor

static CountdownControl()
{
   DefaultStyleKeyProperty.OverrideMetadata(typeof(CountdownControl), 
		new FrameworkPropertyMetadata(typeof(CountdownControl)));
}

As per a previous post on extending an existing control, the DefaultStyleKeyProperty is here to change the metadata for this class to associate a new style with this specific type.

Step 2

Create a ResourceDictionary named CountdownControl.xaml and add the following code

<Style TargetType="{x:Type Controls:CountdownControl}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type Controls:CountdownControl}">
            <Grid>
               <TextBlock Text="{Binding Current, RelativeSource={RelativeSource TemplatedParent}}" />
            </Grid>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

There’s not masses to say here except that this will now display the Current property value as it counts down in a TextBlock. The use of the binding instead of TemplateBinding is covered in a previous post, but basically TemplateBinding is lightweight and does not support the type conversion from an int (the current property) to a string. So we have to use the more verbose Binding syntax to solve this.

Lastly, if you are creating this control in it’s own assembly and haven’t already got one, create a Themes folder in your project and add a Generic.xaml ResourceDictionary inside the folder. Then add the following XAML

<ResourceDictionary.MergedDictionaries>
   <ResourceDictionary Source="/SimpleControl;component/CountdownControl.xaml" />
</ResourceDictionary.MergedDictionaries>

Step 3

Now we can use the CountdownControl by simply adding the following

<Controls:CountdownControl From="30"/>

Note: This assumes you’ve a namespace for the CountdownControls aliased as Controls.

If you run the application now it should display a simple text countdown from 30 to zero.

So whilst our lookless code then got a default look, we now want to re-template it to something a little nicer (although still fairly simple).

We’re going to now re-template the control to use a progress bar to show the countdown. So let’s see the new Style for this.

<Style TargetType="{x:Type c:CountdownControl}">
   <Setter Property="Template">
      <Setter.Value>
          <ControlTemplate TargetType="{x:Type c:CountdownControl}">
             <Grid>
                <ProgressBar Minimum="0" Maximum="{Binding From, RelativeSource={RelativeSource TemplatedParent}}" 
                      Value="{Binding Current, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" Height="20"/>
             </Grid>
          </ControlTemplate>
       </Setter.Value>
    </Setter>
</Style>

As you can see we’re now also using the From property as well as the Current property. We might have also decided to use the IsRunning with a BooleanToVisibilityConverter to hide the progress bar when it reaches zero.

In Summary

We’ve created a control which began by having no UI and was lookless and also very much testable. We then created a basic default look so we could at least see something when designing with the control. Finally we created a nicer UI for our specific needs.

TemplateBinding can be a little too lightweight

TemplateBinding can be used within a ControlTemplate to reference a value from the control that the template has been implemented on, but it has a few issues associated with it.

On the plus side

TemplateBinding is evaluated at compile time giving an increase in performance.

On the negative side

TemplateBinding is a little lightweight on features and in what it can bind to or more specifically how it’s binds. It doesn’t offer all the capabilities of the Binding, for example you cannot apply converters, it doesn’t support two-way binding and most importantly it doesn’t handle the type converting that Binding implements.

So for example

<TextBlock Text="{TemplateBinding MyInteger}" />

where (you guessed it) MyInteger is an int, nothing will be output in this TextBlock. As it cannot convert an int to a string.

Luckily there’s another way of binding to the template using the slightly more verbose TemplatedParent option

<TextBlock Text="{Binding MyInteger, RelativeSource={RelativeSource TemplatedParent}}" />

Unlike the TemplateBinding this is evaluated at runtime and by using the Binding class we can all the goodness associated with Binding.

Designer Metadata – WPF Control Development

When creating a control in WPF the aim is to try to separate the UI from the functionality that implements the control logic. That is to say, create a “lookless” control. A lookless control may potentially have one or more of the following: functionality, properties, events, styles and visual state. The control itself should not know about how it’s displayed but may well know what part’s it might wish to manipulate (and what base types they are).

We want to publish the parts of the control that may be manipulated by a ControlTemplate so that a designer application, such as Visual Studio’s built-in WPF UI designer or Expression Blend, can find out which parts the control manipulates or what styles are used or what states exist within the control.

The following attributes are applied to a control’s class definition to publish various pieces of metadata.

TemplatePart Attribute

A control may be thought of as broken up into sections, for example maybe we’ve created a colour picker type of control which has a section made up of a selection of rectangles each showing a colour and possibly another section which is some for of input (let’s assume a TextBox) which is used to take the hexadecimal representation of a colour.

Within our code we’d declare these parts as follows:

[TemplatePart(Name = PART_HexadecimalInput, Type = typeof(TextBox))]
[TemplatePart(Name = PART_ColourSelectionPanel, Type = typeof(Panel))]
public class ColourPicker : Control
{
   private const string PART_HexadecimalInput = "PART_HexadecimalInput";
   private const string PART_ColourSelectionPanel = "PART_ColourSelectionPanel";

   // implementation
}

Note: The general rule is to name such parts by prefixing with PART_

Now within our implementation of the control we will have some code to get the various parts from the ControlTemplate applied to this control. This is usually handled in the OnApplyTemplate method as per the following

public override void OnApplyTemplate()
{
   base.OnApplyTemplate();

   hexadecimalInput = GetTemplateChild(PART_HexadecimalInput) as TextBox;
   colourSelectionPanel = GetTemplateChild(PART_ColourSelectionPanel) as Panel;
}

Assuming hexadecimalInput is of type TextBox and colourSelectionPanel is a Panel, we now have access to the parts that potentially make up the ControlTemplate. I say potentially because it’s equally possible that somebody re-templates to include only limited functionality, so for example maybe we just want the colour picker then we remove the PART_HexadecimalInput from our ControlTemplate. Thus this code should handle situations where a part is not found in the template.

Once the control has access to the parts (and assuming they exist in the ControlTemplate) we can now attached event handlers to them or manipulate them in different ways.

StyleTypedProperty Attribute

The StyleTypedProperty exposes the properties which are of type Style, for example we wish to extend our ColourPicker to have a property that has the Style applied to the colour selection panel. We declare the property as per any other dependency property (I’ll list below just for completeness)

public static readonly DependencyProperty ColourSelectionPanelStyleProperty =     
                 DependencyProperty.Register(
                 "ColourSelectionPanelStyle",
                 typeof(Style),
                 typeof(ColourPicker),
                 new PropertyMetadata(null));

public Style ColourSelectionPanelStyle
{
   get { return (Style)GetValue(ColourSelectionPanelStyleProperty ); }
   set { SetValue(ColourSelectionPanelStyleProperty , value); }
}

So now we have a property of type Style named ColourSelectionPanelStyle. We want to now expose this via the StyleTypedPropertyAttribute as per

[StyleTypedProperty(Property = "ColourSelectionPanelStyle", StyleTargetType = typeof(Panel))]
public class ColourPicker : Control
{
   // implementation
}

Exposing our style like this means we could easily apply, just the style, to part of our control without the need to clone the whole ControlTemplate.

TemplateVisualState Attribute

In a previous post I talked about using the VisualStateManager (VSM) and how we can create our own strings to represent a control’s different state. These strings are keys defined by the developer to represent various changes within a control.

To publish these states we use the TemplateVisualStateAttribute, for example

[TemplateVisualState(Name = "ColourSelected", GroupName = "SelectionStates")]
public class ColourPicker : Control
{
   // implementation
}

Now within our ControlTemplate we might have a VSM with the VisualState

<VisualStateManager.VisualStateGroups>
   <VisualStateGroup x:Name="ColourPickerGroup">
      <VisualState x:Name="ColourPickedState">
         <!-- Some UI specific code -->
      </VisualState>
   </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

ContentProperty Attribute

The ContentPropertyAttribute can be used to indicate which property is the XAML content property. We might be hard pushed to find a use for the ContentProperty on our example ColourPicker, so instead let’s look at a ResourceKeyConverter class

[ContentProperty("Options")]
public class ResourceKeyConverter : MarkupExtension, IValueConverter
{
   public ResourceDictionary Options { get; set; }
   // implementation
}

Now XAML knows that within the ResourceKeyConverter XAML code the content is of type ResourceDictionary, for example

<UI:ResourceKeyConverter x:Key="resourceConverter">
   <ResourceDictionary>
      <SolidColorBrush Color="Red" x:Key="X" />
      <SolidColorBrush Color="Green" x:Key="Y" />
   </ResourceDictionary>
</UI:ResourceKeyConverter>

If the type of the property is not a string or object the XAML procesoor tries to convert the type using native type conversions or look for a type converter.

VisualStateManager and alternative to Triggers

The VisualStateManager came into being with Silverlight. I’m not a Silverlight developer, but I believe I’m right it saying that Silverlight didn’t support Triggers, hence the VSM was created to emulate aspects of the triggering system (or at least a state change management).

Where the VSM comes into it’s own is the ability to create a control with multiple “states”. Whereby when an event or other state change occurs we can inform the ControlTemplate via a simple string (used to define a state change key). This is similar to various MessageBus implementations for MVVM code. The VSM is literally a simple state machine, so not only can we handle the state changes but also the transitions between changes if we want. Offering the ability to not only change the UI on certain state changes but even do different things depending upon the transitions from state to state.

Note: Bot the Triggering system and the VSM can used toegether if desired.

Let’s see this in action as it’ll make things much clearer. I’ve implemented a simple WatermarkTextBox, initially using Triggers. When the textbox has focus the watermark text is hidden. When the textbox doesn’t have focus AND no text exists within the textbox, the watermark is displayed, otherwise it remains hidden. Here’s the XAML for the control

<Style TargetType="Controls:WatermarkTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="Controls:WatermarkTextBox">
            <Grid>
               <Border BorderThickness="{Binding Path=BorderThickness, 
                   RelativeSource={RelativeSource TemplatedParent}, 
                   Mode=OneWay}" BorderBrush="{Binding Path=BorderBrush, 
                   RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
                  <Grid>                               
                     <ScrollViewer x:Name="PART_ContentHost" Margin="3"/>
                     <TextBlock x:Name="PART_Watermark" 
                         Text="{TemplateBinding Watermark}" FontStyle="Italic" 
                         VerticalAlignment="Center" Margin="5,0,0,0" 
                         FontWeight="Bold" Foreground="Gray"/>
                  </Grid>
               </Border>
            </Grid>

            <ControlTemplate.Triggers>
               <MultiTrigger>
                  <MultiTrigger.Conditions>
                     <Condition Property="IsFocused" Value="True"/>
                  </MultiTrigger.Conditions>
                  <Setter Property="Visibility" 
                            Value="Collapsed" TargetName="PART_Watermark" />
               </MultiTrigger>

               <MultiTrigger>
                  <MultiTrigger.Conditions>
                     <Condition Property="RemoveWatermark" Value="True"/>
                     <Condition Property="IsFocused" Value="False"/>
                  </MultiTrigger.Conditions>
                  <Setter Property="Visibility" 
                            Value="Collapsed" TargetName="PART_Watermark" />
               </MultiTrigger>
            </ControlTemplate.Triggers>

         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

and now the bare bones source code for this implementation looks like this

public class WatermarkTextBox : TextBox
{
   static WatermarkTextBox()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox), 
              new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));

      TextProperty.OverrideMetadata(typeof(WatermarkTextBox),
   	      new FrameworkPropertyMetadata(
                  new PropertyChangedCallback(TextPropertyChanged)));
   }	

   public static readonly DependencyProperty WatermarkProperty =
	DependencyProperty.Register("Watermark", typeof(string), 
           typeof(WatermarkTextBox),
	   new FrameworkPropertyMetadata(String.Empty));

   public string Watermark
   {
      get { return (string)GetValue(WatermarkProperty); }
      set { SetValue(WatermarkProperty, value); }
   }

   private static readonly DependencyPropertyKey RemoveWatermarkPropertyKey
            = DependencyProperty.RegisterReadOnly("RemoveWatermark", 
                    typeof(bool), typeof(WatermarkTextBox),
                    new FrameworkPropertyMetadata((bool)false));

   public static readonly DependencyProperty RemoveWatermarkProperty
            = RemoveWatermarkPropertyKey.DependencyProperty;

   public bool RemoveWatermark
   {
      get { return (bool)GetValue(RemoveWatermarkProperty); }
   }

   static void TextPropertyChanged(DependencyObject sender, 
                     DependencyPropertyChangedEventArgs args)
   {
      WatermarkTextBox watermarkTextBox = (WatermarkTextBox)sender;
      bool textExists = watermarkTextBox.Text.Length > 0;
      if (textExists != watermarkTextBox.RemoveWatermark)
      {
         watermarkTextBox.SetValue(RemoveWatermarkPropertyKey, textExists);
      }
   }
}

Now let’s look at an equivalent ControlTemplate using the VSM

<Style TargetType="Controls:WatermarkTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="Controls:WatermarkTextBox">
            <Grid>
              <VisualStateManager.VisualStateGroups>
                 <VisualStateGroup x:Name="WatermarkGroup">
                    <VisualState x:Name="ShowWatermarkState">
                        <Storyboard>
                           <ObjectAnimationUsingKeyFrames 
                                       Duration="0:0:0" 
                                       Storyboard.TargetName="PART_Watermark" 
                                       Storyboard.TargetProperty="(UIElement.Visibility)">
                              <DiscreteObjectKeyFrame KeyTime="0:0:0" 
                                       Value="{x:Static Visibility.Visible}"/>
                           </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                        </VisualState>
                        <VisualState x:Name="HideWatermarkState">
                           <Storyboard>
                              <ObjectAnimationUsingKeyFrames Duration="0:0:0" 
                                        Storyboard.TargetName="PART_Watermark" 
                                        Storyboard.TargetProperty="(UIElement.Visibility)">
                                 <DiscreteObjectKeyFrame KeyTime="0:0:0" 
                                          Value="{x:Static Visibility.Collapsed}"/>
                              </ObjectAnimationUsingKeyFrames>
                           </Storyboard>
                        </VisualState>
                 </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

               <Border BorderThickness="{Binding Path=BorderThickness, 
                   RelativeSource={RelativeSource TemplatedParent}, 
                   Mode=OneWay}" BorderBrush="{Binding Path=BorderBrush, 
                   RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
                  <Grid>                               
                     <ScrollViewer x:Name="PART_ContentHost" Margin="3"/>
                     <TextBlock x:Name="PART_Watermark" 
                         Text="{TemplateBinding Watermark}" FontStyle="Italic" 
                         VerticalAlignment="Center" Margin="5,0,0,0" 
                         FontWeight="Bold" Foreground="Gray"/>
                  </Grid>
               </Border>
            </Grid>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

Now the source code is basically the same as previously listed but with the following change to TextPropertyChanged

static void TextPropertyChanged(DependencyObject sender, 
                  DependencyPropertyChangedEventArgs args)
{
   WatermarkTextBox watermarkTextBox = (WatermarkTextBox)sender;
   bool textExists = watermarkTextBox.Text.Length > 0;
   if (textExists != watermarkTextBox.RemoveWatermark)
   {
      watermarkTextBox.SetValue(RemoveWatermarkPropertyKey, textExists);
   }

   // added to update the VSM
   watermarkTextBox.UpdateState();
}

and the following new methods

private void UpdateState()
{
   bool textExists = Text.Length > 0;
   var watermark = GetTemplateChild("PART_Watermark") as FrameworkElement;
   var state = textExists || IsFocused ? "HideWatermarkState" : "ShowWatermarkState";

   VisualStateManager.GoToState(this, state, true);
}

protected override void OnGotFocus(RoutedEventArgs e)
{
   base.OnGotFocus(e);
   UpdateState();
}

protected override void OnLostFocus(RoutedEventArgs e)
{
   base.OnLostFocus(e);
   UpdateState();
}

So we’ve had to put a little extra work into the VSM version, but the key bit is in UpdateStatus where we tell the VSM to GoToState. In this we’re in essence sending a string message to the VSM to tell it to “trigger” it’s storyboard for the given state.

What this means is that we could define many changes in state that could then be handled via the VSM.

We could (as seems to occur in some controls) define states which our ControlTemplate does nothing with. This allows us to define states within the control’s code which somebody might wish to hook into. These might be declared in the default ControlTemplate as empty elements as per the code below

<VisualState x:Name="DoSomethingSomeDay" />

Then anyone defining their own ControlTemplate can override these states if they wish.

When defining our states a control should publish the states that it implements.uses using the TemplateVisualState attribute. This is not a requirement for the code to work bbut obviously tells anything/anyone wishing to retemplate the control, what states it codes to, so for our example we would mark the WatermarkTextBox thus

[TemplateVisualState(Name = "ShowWatermarkState", GroupName = "WatermarkGroup")]
[TemplateVisualState(Name = "HideWatermarkState", GroupName = "WatermarkGroup")]
public class WatermarkTextBox : TextBox
{
   // .. implementation
}

Along with the ability to set different visual states we can also create transitions (VisualTransitions) between two states, for example if a state changes from one state to another maybe we want to change the colour of the background of a control to show the transition. In some ways we can achieve most of what we want in the various VisualStates, but the VisualTransition can show difference based on the different workflows of a state transition.

Below is a simple example for the WatermarkTextBox, which could have been achieved solely with states, but just gives an idea of what you can do. Here we transition between ShowWatermarkState and HidewatermarkState and back. Using a DoubleAnimation we alter the Opacity of the watermark text.

<VisualStateManager.VisualStateGroups>
   <VisualStateGroup x:Name="WatermarkGroup">
       <VisualStateGroup.Transitions>
           <VisualTransition From="ShowWatermarkState" To="HideWatermarkState">
              <Storyboard>
                 <DoubleAnimation Storyboard.TargetName="PART_Watermark"
                                  Storyboard.TargetProperty="Opacity" From="1"
                                  To="0" Duration="0:0:2" />
               </Storyboard>                                        
            </VisualTransition>
            <VisualTransition From="HideWatermarkState" To="ShowWatermarkState">
               <Storyboard>
                  <DoubleAnimation Storyboard.TargetName="PART_Watermark"
                                   Storyboard.TargetProperty="Opacity" From="0"
                                   To="1" Duration="0:0:2" />
               </Storyboard>
            </VisualTransition>
         </VisualStateGroup.Transitions>
         <VisualState x:Name="ShowWatermarkState">
            <Storyboard>
               <ObjectAnimationUsingKeyFrames Duration="0:0:0" 
                             Storyboard.TargetName="PART_Watermark" 
                             Storyboard.TargetProperty="(UIElement.Visibility)">
                  <DiscreteObjectKeyFrame KeyTime="0:0:0" 
                             Value="{x:Static Visibility.Visible}"/>
               </ObjectAnimationUsingKeyFrames>
            </Storyboard>
         </VisualState>
         <VisualState x:Name="HideWatermarkState">
            <Storyboard>
               <ObjectAnimationUsingKeyFrames Duration="0:0:0" 
                             Storyboard.TargetName="PART_Watermark" 
                             Storyboard.TargetProperty="(UIElement.Visibility)">
                   <DiscreteObjectKeyFrame KeyTime="0:0:0" 
                             Value="{x:Static Visibility.Collapsed}"/>
               </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>                                
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Now the above will not work quite as expected on the first time the texbox gets focus as no transition takes place so in the code if we add

public override void OnApplyTemplate()
{
   base.OnApplyTemplate();
   VisualStateManager.GoToState(this, "ShowWatermarkState", true);
}

Just to seed the initial state, then as the textbox gets focus the transition from ShowWatermarkState to HideWatermarkState takes place.

DataTemplates and DataTriggers in WPF

One of the cool features of WPF is the way we can define a UI based upon the data type used.

For example, assuming a very simple view model

public class PersonViewModel : ReactiveObject
{
   private string firstName;
   private string lastName;
   private int age;

   public string FirstName
   {
      get { return firstName; }
      set { this.RaiseAndSetIfChanged(ref firstName, value); }
   }

   public string LastName
   {
      get { return lastName; }
      set { this.RaiseAndSetIfChanged(ref lastName, value); }
   }

   public int Age
   {
      get { return age; }
      set { this.RaiseAndSetIfChanged(ref age, value); }
   }
}

We might have a parent view model returning a PersonViewModel type or maybe an ItemsControl that has an ObservableCollection of PersonViewModel types. We can handle the bindings in the standard way but we can also associate a UI with a data type using DataTemplates.

A simple example of this is seem with the following code

<ResourceDictionary>
   <Model:PersonViewModel x:Key="model"/>
</ResourceDictionary>

<Button Content="{Binding Source={StaticResource model}}"/>

With the above the button content will display the namespace.objecttype, i.e. MyTestApp.PersonViewModel which is of little use, but if we create a DataTemplate as per the following XAML, we get something more useable

<DataTemplate DataType="{x:Type ta:PersonViewModel}">
   <TextBlock>                    
      <TextBlock.Text>
         <MultiBinding StringFormat="{}{0} {1} aged {2}">
            <Binding Path="FirstName" />
            <Binding Path="LastName" />
            <Binding Path="Age" />
         </MultiBinding>
      </TextBlock.Text>
   </TextBlock>
</DataTemplate>

Now our button will display the “FirstName LastName aged Age” text, where obviously FirstName, LastName and Age are taken from our view model.

Note: You can use a DataTemplate against any ContentControl, so we can see this template used on a button, a label or other control that expects/handles a ContentControl. Whereas the likes of a TextBlock’s Text property expects a string, so this will not work there.

The DataTemplate is also used in the ItemTemplate of a ListBox (for example)

<ListBox ItemsSource="{Binding People}" />

Using the above, where People is an ObservableCollection property. The ItemTemplate of the ListBox uses the DataTemplate previously defined. Alternatively we can create the DataTemplate within the ItemTemplate as per

<ListBox ItemsSource="{Binding People}">
   <ListBox.ItemTemplate>
      <DataTemplate>
         <TextBlock>
            <TextBlock.Text>
               <MultiBinding StringFormat="{}{0} {1} aged {2}">
                  <Binding Path="FirstName" />
                  <Binding Path="LastName" />
                  <Binding Path="Age" />
               </MultiBinding>
            </TextBlock.Text>
         </TextBlock>
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

Along with DataTemplate we can define DataTemplate Triggers, for example

<DataTemplate DataType="{x:Type ta:PersonViewModel}">
   <TextBlock x:Name="text">                    
      <TextBlock.Text>
         <MultiBinding StringFormat="{}{0} {1} aged {2}">
            <Binding Path="FirstName" />
            <Binding Path="LastName" />
            <Binding Path="Age" />
         </MultiBinding>
      </TextBlock.Text>
   </TextBlock>
   <DataTemplate.Triggers>
      <Trigger SourceName="text" Property="IsMouseOver" Value="True">
         <Setter TargetName="text" Property="Background" Value="GreenYellow" />
      </Trigger>
   </DataTemplate.Triggers>
</DataTemplate>

So now anything use the DataTemplate will also apply the trigger code to the UI view of this data.

Styles in WPF

Styles in WPF allow us a reusable means of applying styling properties to controls. So for example, if we’ve decided that all the text boxes within a control, window or our app. should be displayed with a LemonChiffon background colour, instead of having something like this

<TextBox Background="LemonChiffon" x:Name="FirstName"/>
<TextBox Background="LemonChiffon" x:Name="LastName"/>
<TextBox Background="LemonChiffon" x:Name="Age"/>

we could create a style that’s applied to all TextBoxes, like the following

<ResourceDictionary>
   <Style TargetType="{x:Type TextBox}">
      <Setter Property="Background" Value="Gray" />
   </Style>
</ResourceDictionary>

...

<TextBox x:Name="FirstName"/>
<TextBox x:Name="LastName"/>
<TextBox x:Name="Age"/>

The style is defined as part of the ResourceDictionary and in this instance as no x:Key is set on the style resource it’s applied to all TextBoxes. If you were to create more than one style for a TextBox in this way, the last one defined is the one that will be used to style the TextBoxes. In such a situation where no key is defined, implicitly the key of x:Key=”{x:Type TextBox}” is used instead.

Note: We set the properties of the UIElement we wish to change using the Setter tag and the Property is obviously the property on the UIElement and the value is the value we wish to apply. I know, it’s obvious but I thought I’d mention it anyway.

So if you had a desire to have multiple background colours, for example maybe one colour for required fields and another for options, you would need to give one or both styles a key name to be used by the TextBox. For example

<Style x:Key="Required" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Background" Value="LemonChiffon" />
</Style>

<Style x:Key="Optional" TargetType="{x:Type TextBox}">
   <Setter Property="Background" Value="BlanchedAlmond" />
</Style>

...

<TextBox x:Name="FirstName" Style="{StaticResource Required}"/>
<TextBox x:Name="LastName" Style="{StaticResource Required}"/>
<TextBox x:Name="Age" Style="{StaticResource Optional}"/>

If the Optional key didn’t exist then all TextBoxes without a style applied will take on the style without a x:Key.

Styles can also inherit from other styles, so let’s say we want to inherit from the newly created Required style for a TextBox and create a style based on it but which also adds a Bold font. We use the BasedOn attribute

<Style x:Key="Important" TargetType="{x:Type TextBox}" BasedOn="{StaticResource Required}">
   <Setter Property="FontWeight" Value="Bold" />
</Style>

So the “Important” style now inherits the LemonChiffon background and adds the Bold font.

Styles, of course, can be placed in other assemblies and referenced via an application using the Pack URI for example, in my App.xaml I could reference the xaml from an assembly as follows

<Application.Resources>
   <ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Themes/generic.xaml" />-->
</Application.Resources>

Note: Whilst this code works, it doesn’t display the style at design time via the XAML designer. It will display at runtime.

Along with the “basic” styles of a control we can declare other styling attributes such as Triggers.

<Style x:Key="Required" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Background" Value="LemonChiffon" />
   <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
         <Setter Property="Background" Value="GreenYellow" />
      </Trigger>
   </Style.Triggers>
</Style>

In the above we not add the trigger to change the background colour when the mouse is over the control.

Note: IsMouseOver comes from the UIElement.

Basics of extending a WPF control

Occasionally we need to extend an existing WPF control. We might apply a different style to the control, or applying a new control template both using XAML. Or maybe this isn’t sufficient and we need to add functionality to the control itself using code.

In this post we’ll not be touching the style, but we will be looking at extending an existing control’s functionality and changing the control template to use the new functionality. This result is not mean’t to be a production ready control (although hopefully it will be) but is more aimed at the steps required to create our new control etc.

Through this post we’ll create a simple watermark text box. In other word a text box which displays text, then when the control gets focus the text will disappear and when the control loses focus and only if no text has been typed in, the watermark will reappear.

The steps….

  1. Create a new control and derive from the WPF TextBox, create an initial style for the control and expose this to allows us to reference and use the control elsewhere.
  2. Add our new properties, such as a string property for the Watermark text and a flag to state whether text exists in the TextBox
  3. Create the new control template to work with the new control properies

Step 1

We’ve already decided that we want to simply added some functionality to an existing TextBox, so first we create a new class (in the file named WatermarkTextBox,cs) and derive it from TextBox.

public class WatermarkTextBox : TextBox
{
   static WatermarkTextBox()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox), 
             new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
   }
}

The important addition here is the static constructor and the DefaultStyleKeyProperty.OverrideMetadata. Without this the WatermarkTextBox will get the default theme for the TextBox, but we know we’re going to need to change this, so this line sets the default style to one with a target type of WatermarkTextBox.

If you ran code with this class as it is, you’d seen no output as we’ve not defined the default style yet. If you comment out the line in DefaultStyleKeyProperty.OverrideMetadata you’ll obviously see the default style for a TextBox.

So to complete step 1. We need to create a .xaml file (named WatermarkTextBox.xaml), so in VS2012 add a new Resource Dictionary and then add the following code to it

<Style TargetType="Controls:WatermarkTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
</Style>

You’ll obviously need to add the namespace, which I’ve named as Controls.

I’ve in essence defined a style for this control which obviously adds nothing and thus looks like a TextBox’s default style. But we’ll flesh this out later. For now this will display nothing unless we create a Generic.xaml file.

Themes\Generic.xaml

By default WPF expects any generic styles etc. to be stored in a folder named Themes off of the project. Here we create another Resource Dictionary file name Generic.xaml. To this we add the following code

<ResourceDictionary.MergedDictionaries>
   <ResourceDictionary Source="/SimpleControl;component/WatermarkTextBox.xaml" />
</ResourceDictionary.MergedDictionaries>

We’re telling WPF to merge the WatermarkTextBox.xaml file into the Themes\Generic.xaml Resource Dictionary.

Step 2

Step 1 was basically about getting the plumbing in place to allow us to work with our new control, so let’s now added some new functionality to the WatermarkTextBox. This step will write all the code in the .cs file so go to that file and type dpp and tab (twice) within the class to use the DependencyProperty code snippet that ships with VS2012. Select 0 — Dependency Property — default value.

Give the property the name Watermark. This will be the text displayed as the watermark. VS should fill in the name and create the snippet. We need to change the text new FrameworkPropertyMetadata((bool)false) to new FrameworkPropertyMetadata(String.Empty) so that this property is a string and by default displays an empty string, i.e. nothing. Also we need to change the from bool to string elsewhere.

So the code should look like this (comments and regions removed)

public static readonly DependencyProperty WatermarkProperty =
         DependencyProperty.Register("Watermark", typeof(string), 
                      typeof(WatermarkTextBox),
		      new FrameworkPropertyMetadata(String.Empty));

   public string Watermark
   {
      get { return (string)GetValue(WatermarkProperty); }
      set { SetValue(WatermarkProperty, value); }
   }

Now we want the watermark to disappear when the control gains focus which is easy enough, but we also want it so that when the control loses focus the watermark is redisplayed but only if no text exists. So we need a property to tell us whether text exists. It’s not something that can be altered outside of the class so under the Dependency Property we just added (and within the class) type dp and tab twice selecting the Read-Only Dependency Property — default value option. To added a read only dependency property.

Give the name RemoveWatermark and let the snippet fill in the rest. This code snippet added a SetRemoveWatermark method, we don’t need this as the value is going to be determined by whether there’s text in the TextBox and therefore cannot be set directly. The code added should therefore look like this (comments and regions removed).

private static readonly DependencyPropertyKey RemoveWatermarkPropertyKey = 
            DependencyProperty.RegisterReadOnly("RemoveWatermark", typeof(bool), 
                typeof(WatermarkTextBox),
                new FrameworkPropertyMetadata((bool)false));

public static readonly DependencyProperty RemoveWatermarkProperty =                 
            RemoveWatermarkPropertyKey.DependencyProperty;

public bool RemoveWatermark
{
   get { return (bool)GetValue(RemoveWatermarkProperty); }
}

Finally for the code we need to put the code in place to update RemoveWatermark. So we’ve already mentioned that this code will depend on there being text in the TextBox. So naturally we’ll need to override the TextPropertyChanged event. To do this we need to add the following code to the static constructor

TextProperty.OverrideMetadata(typeof(WatermarkTextBox),
	new FrameworkPropertyMetadata(new PropertyChangedCallback(TextPropertyChanged)));

This tells TextBox TextProperty to call our TextPropertyChanged event for WatermarkTextBox types. So now let’s add the TextPropertyChanged code

static void TextPropertyChanged(DependencyObject sender, 
                  DependencyPropertyChangedEventArgs args)
{
   WatermarkTextBox watermarkTextBox = (WatermarkTextBox)sender;

   bool textExists = watermarkTextBox.Text.Length > 0;
   if (textExists != watermarkTextBox.RemoveWatermark)
   {
      watermarkTextBox.SetValue(RemoveWatermarkPropertyKey, textExists);
   }
}

This is simple enough. The sender should always be of type WatermarkTextBox so we simply cast it. We then check whether the Text.Length is greater than zero to see whether text exists. If the RemoveWatermark property differs from the new value we set the value on the RemoveWatermarkPropertyKey.

If we run a test app with the WatermarkTextBox it will still look like a TextBox but now has extra properties so if you’re working through this example go to your test app and add a Watermark string to your WatermarkTextBox ready for the next step. So it looks something like this

<Controls:WatermarkTextBox Watermark="Search" />

Step 3

We now need to fill in the control’s style. Open the WatermarkTextBox.xaml file and insert the following code into the Style created previously

<Setter Property="Template">
   <Setter.Value>
      <ControlTemplate TargetType="Controls:WatermarkTextBox">
                    
         <Border BorderThickness="{Binding Path=BorderThickness, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" 
                 BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
            <Grid>
               <ScrollViewer x:Name="PART_ContentHost" Margin="3"/>
                  <TextBlock x:Name="watermarkText" 
                        Text="{TemplateBinding Watermark}" 
                        FontStyle="Italic" 
                        VerticalAlignment="Center"
			Margin="5,0,0,0" 
                        FontWeight="Bold" 
                        Foreground="Gray"/>
             </Grid>
          </Border>
                    
         <ControlTemplate.Triggers>
            <MultiTrigger>
               <MultiTrigger.Conditions>
                  <Condition Property="IsFocused" Value="True"/>
               </MultiTrigger.Conditions>
               <Setter Property="Visibility" Value="Collapsed" TargetName="watermarkText" />
            </MultiTrigger>

            <MultiTrigger>
               <MultiTrigger.Conditions>
                  <Condition Property="RemoveWatermark" Value="True"/>
                  <Condition Property="IsFocused" Value="False"/>
               </MultiTrigger.Conditions>
               <Setter Property="Visibility" Value="Collapsed" TargetName="watermarkText" />
            </MultiTrigger>
         </ControlTemplate.Triggers>
      </ControlTemplate>
   </Setter.Value>
</Setter>

There’s a lot to take in there, but basically we’re setting the Template for the WatermarkTextBox. The first part is the ControlTemplate whereby we replace the TextBox’s default look with out own, adding a TextBlock which will display our Watermark text.

Note: The Textbox’s actually Template is far larger than the one shown above but basically we’re only really interested in the PART_ContentHost for this sample. But feel free to use Blend or whatever you prefer to edit the whole template if you wish.

As originally decided, we need this text to disappear when the control gets focus and reappear if the control loses focus AND there’s no text in the text box. So we create the two triggers.

The fist checks the IsFocused property and if it’s true collapses the water mark text. The second trigger checks whether we need to remove the watermark AND the IsFocused is False. If it is then the water mark is collapsed.

And that’s it, we’ve created a simple control, added properties, created the default style for the control and made it available to other code (outside it’s assembly).