Category Archives: WPF

Binding to the TabControl’s ItemsSource (and more)

I couldn’t come up with a good title for this post but what I really want to cover is this…

I want to create view models and have a TabControl dynamically create the TabItems for the view models and then automatically assign/associate the corresponding view to the tab’s visual tree for each view model.

Often when we create a TabControl (by the way the concepts listed here work equally well for ItemsControl types), we usually declare everything in XAML, each TabItem is bound to our ViewModel, we supply the header etc. But what I require is a more dynamic way of creating the TabControl’s TabItems via the view model.

Let’s use an example. I’m going to create a TabControl with TabItems similar to the sections within an Outlook Contact details view. So we’ll have a tab for the Contact Details, the Internet Details, the Phone Numbers and the Addresses. In this example we will supply each of the relevant ViewModels via an ObservableCollection and bind this to the TabControls ItemsSource, but before that let’s see the example view models

public class ContactDetailsViewModel
{
   public static string Name
   {
      get { return "Contact Details"; }
   }

   public string Content
   {
      get { return "Contact Details Content"; }
   }
}

The other view models will all take the same form as this one (I’ll still list them for completeness). In these example view models we’ll assume the Content property may be one of many properties that the corresponding view will bind to. i.e. we’ll end up creating many properties which in turn will get bound to a view.

As we want the TabControl to dynamically create TabItems, we’ll also need to supply the TabItem Header via the view model (or some other mechanism), so this is where the Name property comes in.

Before we look at the “outer” view model that the TabControl itself binds to, I’ll list those other view models as mentioned previously

public class InternetViewModel
{
   public static string Name
   {
      get { return "Internet"; }
   }

   public string Content
   {
      get { return "Internet Content"; }
   }
}

public class PhoneNumbersViewModel
{
   public static string Name
   {
      get { return "Phone Numbers"; }
   }

   public string Content
   {
      get { return "Phone Numbers Content"; }
   }
}

public class AddressesViewModel
{
   public static string Name
   {
      get { return "Addresses"; }
   }

   public string Content
   {
      get { return "Addresses Content"; }
   }		
}

Now let’s look at the view model which supplies the TabControl with the ItemsSource data, i.e. it encapsulates the child view models.

public class ContactViewModel
{
   public ContactViewModel()
   {
      Details = new ObservableCollection<object>
      {
         new ContactDetailsViewModel(),
         new InternetViewModel(),
         new PhoneNumbersViewModel(),
         new AddressesViewModel()
      };
   }

   public ObservableCollection<object> Details { get; private set; }
}

As you can see, we create a collection of the view models which will be used to populate the ItemsSource on the TabControl.

Let’s take a look at how we might use this view model within the view (we’ll assume the view’s DataContext has been assigned a ContactViewModel instance by whatever means you like). So this first example of our view is very basic mainly to demonstrate the ItemsSource binding, this will simply display the correct number of TabItems and set the header to the Name property from our view models

<TabControl ItemsSource="{Binding Details}">
   <TabControl.ItemContainerStyle>
      <Style TargetType="{x:Type TabItem}">
         <Setter Property="Header" Value="{Binding Name}" />
      </Style>
   </TabControl.ItemContainerStyle>
</TabControl>

Pretty minimalist, but it’s a good starting point. If you were to run the code thus far, you’ll notice that initially no tab is selected, so we could add a SelectedIndex or SelectedItem property to the TabControl and the relevant binding and view model properties to enable the selected item to be set and tracked. But for now, just click on a tab yourself. When you select a tab you’ll notice the TabItem’s content is the TypeName of the selected view model. This is good as it tells us our view model’s are connected to the TabItems, but ofcourse it’s of no use in our end application, so let’s create four UserControls, named ContactDetailsView, InternetView, PhoneNumbersView and AddessesView and simply give each of them the following

<Grid>
   <TextBlock Text="{Binding Content}" />
</Grid>

Again, in our real world app. each view would differ as would the view model’s properties, but hopefully you get the idea.

We now need to associate the view with the selected view model, a simple way to do this is as follows. Add the following to the TabControl code that we wrote earlier

<TabControl.Resources>
   <DataTemplate DataType="{x:Type tabControlViewModel:ContactDetailsViewModel}">
      <tabControlViewModel:ContactDetailsView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type tabControlViewModel:InternetViewModel}">
      <tabControlViewModel:InternetView/>
   </DataTemplate>
   <DataTemplate DataType="{x:Type tabControlViewModel:PhoneNumbersViewModel}">
      <tabControlViewModel:ContactDetailsView/>
   </DataTemplate>
   <DataTemplate DataType="{x:Type tabControlViewModel:AddressesViewModel}">
      <tabControlViewModel:ContactDetailsView/>
   </DataTemplate>
</TabControl.Resources>

Now if you run the code each selected TabItem will display the corresponding view for the selected view model, using the DataTemplate to select the correct view. If you’re not convinced, for each of the views, change the TextBlock’s ForeGround colour to see that each view is different and thus a different view is display for each view model.

This is a massive step forward and we could stop at this point and be happy but…

Taking it a stage further

Note: This has not been thoroughly tested so use at your own discretion

Using the resources and DataTemplates is a good solution, but I’d rather like something like Caliburn Micro etc. where a view locator creates the view automatically for me. So let’s have a go at producing something like this.

First off our TabControl now looks like this

<TabControl ItemsSource="{Binding Details}" 
      ContentTemplateSelector="{StaticResource Selector}">
   <TabControl.ItemContainerStyle>
      <Style TargetType="{x:Type TabItem}">
         <Setter Property="Header" Value="{Binding Name}" />
      </Style>
   </TabControl.ItemContainerStyle>
</TabControl>

The change from our first version is the ContentTemplateSelector. Obviously we’ll need to add the following to the Resource section of our Window or UserControl

   <tabControlViewModel:ViewTemplateSelector x:Key="Selector"/>

Now let’s write the ViewTemplateSelector. Basically the ViewTemplateSelector is derived from the DataTemplateSelector and what will happen is – when a tab is selected, the ContentTemplateSelector will be used to call our ViewTemplateSelector’s SelectTemplate method. Our ViewTemplateSelector will handle the calls to SelectTemplate and try to locate a view in the same assembly as the view model currently associated with a tab. We try to find a view with matches the name of the view model type but without the Model suffix. So for example for our InternetViewModel, we’ll try to find an InternetView type in the same assembly as the view model. We’ll then create an instance of this and attach to a DataTemplate before returning this to the TabControl.

One thing we need to be aware of is that unless we wish to instantiate a new instance of the view every time an item is selected, we’ll need to cache the data templates.

Anyway here’s the code as I currently have it

public class ViewTemplateSelector : DataTemplateSelector
{
   private readonly Dictionary<string, DataTemplate> dataTemplates = 
                 new Dictionary<string, DataTemplate>();

   public override DataTemplate SelectTemplate(object item, DependencyObject container)
   {
      var contentPresent = container as ContentPresenter;
      if (contentPresent != null)
      {
         const string VIEWMODEL = "ViewModel";
         const string MODEL = "Model";

         if (item != null)
         {
            var type = item.GetType();
            var name = type.Name;
            if (name.EndsWith(VIEWMODEL))
            {
               name = name.Substring(0, name.Length - MODEL.Length);
               if (dataTemplates.ContainsKey(name))
                  return dataTemplates[name];

               var match = type.Assembly.GetTypes().
                      FirstOrDefault(t => t.Name == name);
               if (match != null)
               {
                  var view = Activator.CreateInstance(match) as DependencyObject;
                  if (view != null)
                  {
                     var factory = new FrameworkElementFactory(match);
                     var dataTemplate = new DataTemplate(type)
                     {
                        VisualTree = factory
                     };
                     dataTemplates.Add(name, dataTemplate);
                     return dataTemplate;
                  }
               }
            }
         }
      }
      return base.SelectTemplate(item, container);
   }
}

Now we should have a TabControl whose TabItems are generated based upon the ItemsSource collection of view models. A view is now created based upon the view name and automatically inserted into corresponding TabItem.

WPF Controls and Virtualization

Some of the built-in WPF control can be virtualized and some are virtualized by default. See Optimizing Performance: Controls.

I’m working on migrating a WinForm application to WPF, in doing so I happily recreated the code to load a ComboBox with a fairly large amount of data from a web service call. In the Windows Forms ComboBox this seemed to be have fairly good performance. Not so in the WPF ComboBox!

Some WPF controls, such as the ComboBox create their list control/dropdown to accommodate all items, therefore all items are rendered to the popup associated with it. It then uses a ScrollViewer to handle the scrolling of this large view object. Obviously when we’re talking about something like 10,000+ items (as I’m populating it with), clicking the dropdown button results in a very slow display of the associated popup whilst it’s busy rendering non-visible items.

What would be preferably is if we could load only the items to fit the dropdown space into the popup and have the scrollbar “think” that there’s more data, then we can “virtualize” our loading of data into the UI control.

We do this using the following code

<ComboBox ItemsSource="{Binding}">
   <ComboBox.ItemsPanel>
      <ItemsPanelTemplate>
         <VirtualizingStackPanel />
      </ItemsPanelTemplate>
   </ComboBox.ItemsPanel>
</ComboBox>

Other ItemsControl objects

In the case of the WPF ListView and ListBox, both are virtualized by default.

However, to paraphrase “Optimizing Performance: Controls”

By default WPF ListBoxes use UI virtualization when used with databinding, however if you add ListBoxItem’s explicitly the ListBox does not virtualize.

The TreeView can be enabled using the following code

<TreeView ItemsSource={Binding} VirtualizingStackPanel.IsVirtualizing="True" />

The ContextMenu can also be virtualized.

Scrolling

We might find that an ItemsControl, for example a ListBox, is slow when scrolling. In this case we can use the attached property VirtualizingStackPanel.VirtualizationMode as per

<ListBox ItemsSource={Binding} VirtualizingStackPanel.VirtualizationMode="Recycling" />

Automatically update a WPF Popup position

I wanted a means to automatically reposition a popup in relation to it’s placement target – for example I created a popup that was displayed to the right of another control (the placement target), but when the control’s parent window moved the popup (by default) does not move with it – I needed it to reposition in relation to the placement target.

So I’ve implemented the following behavior to automatically reposition the popup when the parent window is moved

public class AutoRepositionPopupBehavior : Behavior<Popup>
{
   private const int WM_MOVING = 0x0216;

   // should be moved to a helper class
   private DependencyObject GetTopmostParent(DependencyObject element)
   {
      var current = element;
      var result = element;

      while (current != null)
      {
         result = current;
         current = (current is Visual || current is Visual3D) ? 
            VisualTreeHelper.GetParent(current) :
            LogicalTreeHelper.GetParent(current);
      }
      return result;
   }

   protected override void OnAttached()
   {
      base.OnAttached();

      AssociatedObject.Loaded += (sender, e) =>
      {
         var root = GetTopmostParent(AssociatedObject.PlacementTarget) as Window;
         if (root != null)
         {
            var helper = new WindowInteropHelper(root);
            var hwndSource = HwndSource.FromHwnd(helper.Handle);
            if (hwndSource != null)
            {
               hwndSource.AddHook(HwndMessageHook);
            }
         }
      };
   }

   private IntPtr HwndMessageHook(IntPtr hWnd, 
           int msg, IntPtr wParam, 
           IntPtr lParam, ref bool bHandled)
   {
      if (msg == WM_MOVING)
      {
         Update();				
      }
      return IntPtr.Zero;
   }

   public void Update()
   {
      // force the popup to update it's position
      var mode = AssociatedObject.Placement;
      AssociatedObject.Placement = PlacementMode.Relative;
      AssociatedObject.Placement = mode;
   }
}

So to use the above code we simple use the following XAML within a popup element

<i:Interaction.Behaviors>
   <behaviors:AutoRepositionPopupBehavior />
</i:Interaction.Behaviors>

When the AssociatedObject is loaded we locate the topmost window hosting the AssociatedObject and then we hook into the message queue watching for the Window WM_MOVEING message. On each WM_MOVEING message, we update the placement of the popup. To get the Popup to recalculate its position we need to change the placement to something other than what it’s set as, i.e. it needs to change. Then when we reset the placement to our original placement, the Popup position is recalculated.

This code could be improved by checking the Placement and ensuring it changes – in the code above I simply set to PlacementMode.Relative because I know my code a different PlacementMode. Also the above code does not handle the Popup repositioning in the PlacementRectangle is used. Also my requirement doesn’t include the resizing of the PlacementTarget.

I’ll leave those changes until I need them…

Update

Seems I did need to handle resizing of the PlacementTarget so I’ve now added the following to the OnAttached method

AssociatedObject.LayoutUpdated += (sender, e) => Update();

and that appears to solve that problem.

WPF Adorners

An Adorner is a way of extending controls, generally by adding visual cues (or extra functionality). For example a visual cue might be adding drag and drop visuals when users try to drag and drop data onto a control or maybe we want to add resizing handles to controls within some form of UI design surface.

We can implement much of the same sort of visual cues and/or functionality by override the ControlTemplate or subclassing a control, but the Adorner offers a way to associate these cues/functionality to any type of control.

One example Adorner you may have seen is the validation UI whereby we see a red border around a control when validation fails and ofcourse we can extend this UI further if we wish.

Let’s take a look at how we might implement such an Adorner and use it.

Adorner

We’re going to start with a very simple Adorner which simply displays a little red triangle on a control – similar to the way Excel would when a note is attached to a cell.

Firstly, we need to create an Adorner. We subclass the Adorner class and supply a constructor which takes a UIElement, which is the element to be adorned.

public class NoteAdorner : Adorner
{
   public NoteAdorner(UIElement adornedElement) : 
      base(adornedElement)
   {
   }
}

This Adorner isn’t of much use. There’s nothing to see. So let’s write some code so that the Adorner displays our little red triangle over the AdornedElement. Remember that this is a layer on top of the AdorndedElement, in this case we’ll not do anything directly to the AdornedElement directly such as you might when handling drag and drop or the likes.

So add the following to the above class

protected override void OnRender(DrawingContext drawingContext)
{
   var adornedElementRect = new Rect(AdornedElement.RenderSize);

   const int SIZE = 10;

   var right = adornedElementRect.Right;
   var left = right - SIZE;
   var top = adornedElementRect.Top;
   var bottom = adornedElementRect.Bottom - SIZE;

   var segments = new[]
   {
      new LineSegment(new Point(left, top), true), 
      new LineSegment(new Point(right, bottom), true),
      new LineSegment(new Point(right, top), true)
   };

   var figure = new PathFigure(new Point(left, top), segments, true);
   var geometry = new PathGeometry(new[] { figure });
   drawingContext.DrawGeometry(Brushes.Red, null, geometry);
}

To apply an Adorner we need to write some code.

If you create a simple WPF application with a TextBox within it, and assuming the TextBox is named NoteTextBox, then we might write in the code behind of the Window class hosting the TextBox control

public MainWindow()
{
   InitializeComponent();

   Loaded += (sender, args) =>
   {
      var adorner = AdornerLayer.GetAdornerLayer(NoteTextBox);
      adorner.Add(new NoteAdorner(NoteTextBox));
   };
}

Note: It’s important to note that if you try and call the GetAdornerLayer on the TextBox before the controls are loaded you will get a null returned and thus cannot apply the adorner. So we need to apply it after the controls are loaded

In the above code we get the AdornerLayer for a control, in this case the TextBox named NoteTextBox, we then add the adorner to it.

If you run the above code you’ll get the triangle displayed over the top of the TextBox control.

One thing you may notice is that, if click on and the Adorned control it will not get focus. The Adorner ofcourse sits atop the AdornedControl and by default will not give focus to the underlying control. Basically we’ve added this control as an overlay to the AdornedElement, so ofcourse its higher in the z-order.

To change this behaviour we can alter the constructor of the NoteAdorner to the following

public NoteAdorner(UIElement adornedElement) : 
   base(adornedElement)
{
   IsHitTestVisible = false;
}

With the IsHitTestVisible set to false you can click on the Adorner UI and the AdornedElement will take focus.

As you’ll have noticed, the way to attach an Adorner is using code, this doesn’t fit so well with the idea of using XAML for such things, i.e. for a designer to handle such adornments. There are several examples on the web of ways to make adorners XAML friendly.

I’m going to implement a very simple attached property class to handle this. Which I’ve listed below

public class AttachedAdorner
{
   public static readonly DependencyProperty AdornerProperty = 
      DependencyProperty.RegisterAttached(
         "Adorner", typeof (Type), typeof (AttachedAdorner), 
         new FrameworkPropertyMetadata(default(Type), PropertyChangedCallback));

   private static void PropertyChangedCallback(
      DependencyObject dependencyObject, 
      DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
   {
      var frameworkElement = dependencyObject as FrameworkElement;
      if (frameworkElement != null)
      {
         frameworkElement.Loaded += Loaded;
      }
   }

   private static void Loaded(object sender, RoutedEventArgs e)
   {
      var frameworkElement = sender as FrameworkElement;
      if (frameworkElement != null)
      {
         var adorner = Activator.CreateInstance(
            GetAdorner(frameworkElement), 
            frameworkElement) as Adorner;
         if(adorner != null)
         {
            var adornerLayer = AdornerLayer.GetAdornerLayer(frameworkElement);
            adornerLayer.Add(adorner);
         }
      }
   }

   public static void SetAdorner(DependencyObject element, Type value)
   {
      element.SetValue(AdornerProperty, value);
   }

   public static Type GetAdorner(DependencyObject element)
   {
      return (Type)element.GetValue(AdornerProperty);
   }
}

And now let’s see how this might be used

<TextBox Text="Hello World" local:AttachedAdorner.Adorner="{x:Type local:NoteAdorner}" />

AdornerLayer and the AdornerDecorator

As discussed (above) – we need to get the get the adorner layer for example AdornerLayer.GetAdornerLayer(NoteTextBox) to add our adorner to. When GetAdornerLayer is called on a Visual object, the code traverses up the visual tree (starting with the supplied UIElement) looking for an Adorner layer. Then returns the first one it finds. Hence if you write your own custom control you will need to explcitly add a place holder on the ControlTemplate denoting where any adorner should be displayed – in other words where you want the adorner layer is.

So for writing our own custom control we need to put in a place holder, the place holder is an AdornerDecorator object

<AdornerDecorator>
   <ContentControl x:Name="PART_Input" />
</AdornerDecorator>

This can only contain a single child element, although ofcourse this element can contain multiple elements that can be adorned. The AdornerDecorator specifies the position of the AdornerLayer within the visual tree.

Custom Binding MarkupExtension

In my previous post MarkupExtension revisited I looked at creating a replacement “Binding” MarkupExtension.

As usual, after posting that I decided to make some changes.

Basically I wanted to create a base class which will allow me to easily create a Binding style MarkupExtension and then the subclass need only worry about the specifics for what it’s going to do. So I present the BindingBaseExtension class.

[MarkupExtensionReturnType(typeof(object))]
public abstract class BindingBaseExtension : MarkupExtension
{
   protected BindingBaseExtension()
   {			
   }

   protected BindingBaseExtension(PropertyPath path)
   {
      Path = path;
   }

   [ConstructorArgument("path")]
   public PropertyPath Path { get; set; }

   public IValueConverter Converter { get; set; }
   public object ConverterParameter { get; set; }
   public string ElementName { get; set; }
   public RelativeSource RelativeSource { get; set; }
   public object Source { get; set; }
   public bool ValidatesOnDataErrors { get; set; }  
   public bool ValidatesOnExceptions { get; set; }
   [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))]
   public CultureInfo ConverterCulture { get; set; }

   public override object ProvideValue(IServiceProvider serviceProvider)
   {
      var pvt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
      if (pvt == null)
         return null;

      var targetObject = pvt.TargetObject as DependencyObject;
      if (targetObject == null)
         return null;

      var targetProperty = pvt.TargetProperty as DependencyProperty;
      if (targetProperty == null)
         return null;

      var binding = new Binding
      {
         Path = Path,
         Converter = Converter,
         ConverterCulture = ConverterCulture,
         ConverterParameter = ConverterParameter,
         ValidatesOnDataErrors = ValidatesOnDataErrors,
         ValidatesOnExceptions = ValidatesOnExceptions,
         Mode = BindingMode.TwoWay,
         UpdateSourceTrigger = UpdateSourceTrigger.Explicit
      };

      if (ElementName != null)
         binding.ElementName = ElementName;
      if (RelativeSource != null)
         binding.RelativeSource = RelativeSource;
      if (Source != null)
         binding.Source = Source;

      var expression = BindingOperations.SetBinding(targetObject, targetProperty, binding);

      PostBinding(targetObject, targetProperty, binding, expression);

      return targetObject.GetValue(targetProperty);
   }

   protected abstract void PostBinding(DependencyObject targetObject, 
      DependencyProperty targetProperty, Binding binding,
      BindingExpressionBase expression);
}

Now I’m not going to go over the code as you can read all about it in the MarkupExtension revisited post, but suffice to say we now inherit from this class and add our extension’s code to an implementation of the PostBinding method (I’m not mad on the method name but for now it’s the best I could think of).

So our DelayBindingExtension will now look like this

public class DelayBindingExtension : BindingBaseExtension
{
   private IDisposable disposable;

   public DelayBindingExtension()
   {			
   }

   public DelayBindingExtension(PropertyPath path) 
      : base(path)
   {
   }

   public int Delay { get; set; }

   protected override void PostBinding(DependencyObject targetObject, 
      DependencyProperty targetProperty, Binding binding,
      BindingExpressionBase expression)
   {
      var subject = new Subject<EventArgs>();

      var descriptor = DependencyPropertyDescriptor.FromProperty(
                          targetProperty, 
                          targetObject.GetType());
      descriptor.AddValueChanged(targetObject, (sender, args) => subject.OnNext(args));

      subject.Throttle(TimeSpan.FromMilliseconds(Delay)).
         ObserveOn(SynchronizationContext.Current).
         Subscribe(_ => expression.UpdateSource());
   }
}

Note: Please be aware that this implementation of the delay binding extension has a possible memory leak. Basically we’re rooting the object with the call to AddValueChanged and not calling RemoveValueChanged the remove this link.

MarkupExtension revisited

In a previous post I looked at using the MarkupExtension to remove the need for adding Converters as resources, see MarkupExtension. For this post I’m going to look at implement a MarkupExtension to in place of a Binding, i.e.

Disclaimer: All the code listed works, but I’ve not tested in all scenarios

<TextBox Text="{Binding SomeProperty}"/>

What are we going to implement ?

WPF in .NET 4.5 has the concept of Delay property on a Binding which is used as follows

<TextBox Text="{Binding SomeProperty, Delay=500}"/>

This is used on a Binding to only update the source (after a change on the target) after a user-specified delay. The most obvious use of such a mechanism is when the user types into a search or filter text box and you don’t want to be searching and filtering for every change. Preferably code will wait for the user to pause for a short time then carry out the search or filter functionality.

Now .NET 4.0 doesn’t have such a property on the Binding class, so we’re going to implement a very basic approximation of the Binding class in .NET 4.0 (mainly because the current project I’m working on targets .NET 4.0).

Why can’t be simply inherit from the Binding class ?

Unfortunately we cannot simply inherit from the Binding class to add our new code. The ProvideValue method of the MarkupExtension is marked as sealed and not override-able. But hey, where would the fun be if it was all that easy…

Let’s write some code

By convention, as with .NET Attributes, we suffix our extension class name with “Extension” but when it’s used, in XAML, the “Extension” part can be ignored. So first up let’s create the barest of bare bones for our DelayBindingExtension.

[MarkupExtensionReturnType(typeof(object))]
public class DelayBindingExtension : MarkupExtension
{
   public override object ProvideValue(IServiceProvider serviceProvider)
   {
      // To be implemented
      return null;
   }
}

Note: The MarkupExtensionReturnType simply gives WPF information on what to expect as the return type from the ProvideValue method.

Let’s take a quick look at how we expect to use this extension in XAML (which should look pretty similar to the .NET 4.5 implementation show earlier)

<TextBox Text="{markupExtensionTest:DelayBinding Path=MyProperty, Delay=500}"/>

Before we implement the ProvideValue method, let’s add the other binding properties which most people will expect to see

[MarkupExtensionReturnType(typeof(object))]
public class DelayBindingExtension : MarkupExtension
{
   public DelayBindingExtension()
   {			
   }

   public DelayBindingExtension(PropertyPath path) 
   {
      Path = path;
   }

   [ConstructorArgument("path")]
   public PropertyPath Path { get; set; }
   public IValueConverter Converter { get; set; }
   public object ConverterParameter { get; set; }
   public string ElementName { get; set; }
   public RelativeSource RelativeSource { get; set; }
   public object Source { get; set; }
   public bool ValidatesOnDataErrors { get; set; }
   public bool ValidatesOnExceptions { get; set; }
   [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))]
   public CultureInfo ConverterCulture { get; set; }

   public int Delay { get; set; }

   public override object ProvideValue(IServiceProvider serviceProvider)
   {
      // To be implemented
      return null;
   }
}	

Right, those properties will make our extension appear like a Binding object, obviously with our addition of the Delay property.

Now it’s time to implement the ProvideValue method. I’m going to use Reactive Extensions to handle the actual delay (throttling) of the property change events. I’ll list the code and then discuss it afterwards

public override object ProvideValue(IServiceProvider serviceProvider)
{
   var pvt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
   if (pvt == null)
      return null;

   var targetObject = pvt.TargetObject as DependencyObject;
   if (targetObject == null)
      return null;

   var targetProperty = pvt.TargetProperty as DependencyProperty;
   if (targetProperty == null)
      return null;

   var binding = new Binding
   {
      Path = Path, 
      Converter = Converter,
      ConverterCulture = ConverterCulture,
      ConverterParameter = ConverterParameter,
      ValidatesOnDataErrors = ValidatesOnDataErrors,
      ValidatesOnExceptions = ValidatesOnExceptions,
      Mode = BindingMode.TwoWay,
      UpdateSourceTrigger = UpdateSourceTrigger.Explicit
   };

   if (ElementName != null)
      binding.ElementName = ElementName;
   if (RelativeSource != null)
      binding.RelativeSource = RelativeSource;
   if (Source != null)
      binding.Source = Source;
  
   var expression = BindingOperations.SetBinding(targetObject, targetProperty, binding);

   var subject = new Subject<EventArgs>();

   var descriptor = DependencyPropertyDescriptor.FromProperty(
                       targetProperty, targetObject.GetType());
   descriptor.AddValueChanged(targetObject, (sender, args) => subject.OnNext(args));

   subject.Throttle(TimeSpan.FromMilliseconds(Delay)).
      ObserveOn(SynchronizationContext.Current).
      Subscribe(_ => expression.UpdateSource());

   return targetObject.GetValue(targetProperty);
}

Note: The first line where we see if the IServiceProvider supports the IProvideValueTarget interface uses the GetService method. If you use the serviceProvider as IProvideValueTarget way of obtaining the interface you’ll find the MarkupExtension will not be able to cast from an InstanceBuilderServiceProvider to the IProvideValueTarget meaning the code will return null and not the actual bound property at design time. At runtine all will work.

So the first few lines of code are all about getting the interfaces and objects we want before proceeding to the interesting part of the method. This is the point where we create a binding object and supply all the information it expects.

Notice also that for ElementName, RelativeSource and Source we check whether the user actually supplied these values before overwriting the default values. This is important. If we set one of these properties to null we might appear to be supplying the properties with the same value they already have (and ordinarily we’d expect nothing to change) but in fact we’ll be causing the Binding to change from an unset state to set and with the value null. This will stop the property using it’s default behaviour.

So for example setting Source to null (even though it will say it’s null), will stop it using any parent DataContext and ofcourse not bind to anything.

Note: we can return a property to it’s default state using DependencyProperty.UnsetValue

After creating the Binding and applying the properties we call BindingOperations.SetBinding to associate the binding with the target object and target property.

Next we’re going to basically connect to the target property value change events on it’s dependency property. This allows us to handle a dependency property’s value changed event in a generic way, so for a TextBox Text property we’ll respond to the TextChanged event whilst if we use this code on a CheckBox we’ll handle the IsChecked change event and so on.

I’m using the Reactive Extensions in this example as it makes things so much simpler. We’re going to create a Subject and then from this we’ll be using Throttle so we can implement the delay, i.e. Throttle will not call the Action associated with the Subscribe method until a period of inactivity on the property change event – the inactivity timeout obviously being the Delay we set, in milliseconds.

When the Subscribe method’s Action method is called we simply tell the binding expression to Update the source and the data is written to the view model.

You’ll notice we return the property value for the target object at the end of the method. Obviously if the property has data when the binding is first created, this will now be displayed when the control is instantiated.

References

WPF behaviors

Behaviors came into WPF via Expression Blend. They’re basically a standardized way of adding extra functionality to WPF classes using XAML. So why not use attached properties you might ask. I’ll discuss the differences as we go.

Let’s look at a real world example…

I’m using Infragistics XamDataGrid to display rows of data, but I would like a simple filtering mechanism so that when the user enters text into a text box, all columns are filtered to show data with the filter text in it. I also want it so that when the text box is cleared the filters are cleared. Then I want a Button to enable me to clear the filter text for me with the click of the button.

How might we implement this ? Well the title of the post is a giveaway, but let’s look at some other possibilities first

  • We could write this in the code-behind but generally we try to stay clear of writing such code and instead would generally prefer use XAML to help make our code reusable across projects
  • We could derive a new class from the XamDataGrid and add dependency properties, but this means the code will only be usable via our new type, so it’s not as useful across other projects as it requires anyone wanting to use a XamDataGrid to use our version
  • We could use attached properties, which allow us to create “external” code, i.e. code not in code behind or in a derived class, which can work in conjunction with a XamDataGrid, but the problem here is that attached properties are written in static classes and we will want to store instance variables with the data (see my reasons for this requirement below). With a static class implementation we would have to handle the management of such data ourselves, not difficult, but not ideal.

The attached properties route looked promising – I’m going to need a property for the associated TextBox (acting as our filter text) and the Button (used to clear the filter) and ofcourse these may be different per instance of a XamDataGrid – I also need to handle the attachment and detachment of event handlers and any other possible state. As mentioned, we could implement such state management ourselves, but behaviors already give us this capability out of the box as they are created on a per instance basis.

So the best way for to think of a behavior is that it’s like attached properties but allows us to create multiple instances of the code and thus saves us a lot of the headaches that might occur managing multiple instance data.

Note: The code I’m about to show/discuss includes Reactive Extension code. I will not go into any depth on what it does or how it works but the main use here is to handle attachment and detachment of events and also to allow throttling of the input, this means as the user types in the filter text box, we do not update the filter until the user stops typing for half a second. This ensures we’re not continually updating the filters on the XamDataGrid as the user types

Creating a behavior

To create a behavior we simply create a class and derive it from the Behavior class which is part of the System.Windows.Interactivity namespace. The Behavior takes a generic argument which defines the type it can be used on. So to start off our code would look like this

public class XamDataGridFilterBehavior : Behavior<XamDataGrid>
{
   protected override void OnAttached()
   {
      base.OnAttached();
   }

   protected override void OnDetaching()
   {
      base.OnDetaching();
   }
}

So the key parts here (apart from the base class which has already been mentioned) are the OnAttached and OnDetaching overrides. So here we can attach and detach from events on the associated class (i.e. the XamDataGrid) and/or handle initialization/disposal of data/objects as required.

Before we look at a possible implementation of these methods, I wrote a simple list of requirements at the top of this post. One was the requirement for a TextBox to be associated with the XamDataGrid to act as the filter text and the other a Button to be associated to clear the filter. So let’s add the dependency properties to our class to implement these requirements.

public static readonly DependencyProperty FilterTextBoxProperty =
   DependencyProperty.Register(
   "FilterTextBox",
   typeof(TextBox),
   typeof(XamDataGridFilterBehavior));

public TextBox FilterTextBox
{
   get { return (TextBox)GetValue(FilterTextBoxProperty); }
   set { SetValue(FilterTextBoxProperty, value); }
}

public static readonly DependencyProperty ResetButtonProperty =
   DependencyProperty.Register(
   "ResetButton",
   typeof(Button),
   typeof(XamDataGridFilterBehavior));

public Button ResetButton
{
   get { return (Button)GetValue(ResetButtonProperty); }
   set { SetValue(ResetButtonProperty, value); }
}

So nothing exciting there, just standard stuff.

Now to the more interesting stuff, let’s implement the OnAttached and OnDetaching code. As I’m using Reactive Extensions we’ll need to have two instance variables, both of type IDisposable to allow us to clean up/detach any event handling. Let’s see all the code

private IDisposable disposableFilter;
private IDisposable disposableReset;

protected override void OnAttached()
{
   base.OnAttached();

   var filter = FilterTextBox;
   if (filter != null)
   {
      disposableFilter = Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
         x => filter.TextChanged += x,
         x => filter.TextChanged -= x).
         Throttle(TimeSpan.FromMilliseconds(500)).
         ObserveOn(SynchronizationContext.Current).
         Subscribe(_ =>
         {
            var dp = AssociatedObject as DataPresenterBase;

            if (dp != null && dp.DefaultFieldLayout != null)
            {
               dp.DefaultFieldLayout.RecordFilters.Clear();
               dp.DefaultFieldLayout.Settings.RecordFiltersLogicalOperator = LogicalOperator.Or;

               foreach (var field in dp.DefaultFieldLayout.Fields)
               {
                  var recordFilter = new RecordFilter(field);
                  recordFilter.Conditions.Add(
                     new ComparisonCondition(ComparisonOperator.Contains, filter.Text));
								                  
                  dp.DefaultFieldLayout.RecordFilters.Add(recordFilter);
               }
           }
      });
   }

   var reset = ResetButton;
   if (reset != null)
   {
      disposableReset = Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
         x => reset.Click += x,
         x => reset.Click -= x).
         ObserveOn(SynchronizationContext.Current).
         Subscribe(_ =>
         {
             FilterTextBox.Text = String.Empty;
             // whilst the above will clear the filter it's throttled so can
             // look delayed - better we clear the filter immediately
             var dp = AssociatedObject as DataPresenterBase;

             if (dp != null && dp.DefaultFieldLayout != null)
             {
                dp.DefaultFieldLayout.RecordFilters.Clear();
             }
        });
    }
}

protected override void OnDetaching()
{
   base.OnDetaching();

   if (disposableFilter != null)
   {
      disposableFilter.Dispose();
      disposableFilter = null;
   }
   if (disposableReset != null)
   {
      disposableReset.Dispose();
      disposableReset = null;
   }
}

This post isn’t mean’t to be about using the RX library or Infragistics, but the basics are that when OnAttached is called we use the RX FromEventPattern method to create our event handler attachment/detachment points. In the case of the TextBox we attach to the KeyDown event on the TextBox, we throttle the Observable for half a second so (as previously mentioned) we don’t update the filters on every change of the TextBox, we delay for half a second to allow the user to pause and then we filter. We also ensure the Subscribe code is run on the UI thread (well as the code that call OnAttached will be on the UI thread we’re simply observing on the current thread, which should be the UI thread). In the Subscribe method we get the AssociatedObject, this is where our Behavior generic argument comes in. The AssociatedObject is the object this behavior is applied to (we’ll see a sample of the XAML code next). Now we clear any current filters and create new ones based upon the supplied TextBox Text property. Finally we connect to the Click event on the supplied ResetButton. When the button is pressed we clear the FilterText and clear the filters.

In the code above I felt that the UX of a delay between clearing the FilterText and the filters clearing (the half a second delay) didn’t feel right when the user presses a button, so in this instance we also clear the filters immediately.

The OnDetaching allows us cleanup, so we dispose of our Observables and that will detach our event handlers and nicely clean up after usage.

How do we use this code in XAML

Finally, we need to see how we use this code in our XAML, so here it is

<TextBox x:Name="filter"/>
<Button Content="Reset" x:Name="reset" />

<XamDataGrid>
   <i:Interaction.Behaviors>
     <controls:XamDataGridFilterBehavior 
        FilterTextBox="{Binding ElementName=filter}" 
        ResetButton="{Binding ElementName=reset}" />
   </i:Interaction.Behaviors>
</XamDataGrid>

And that’s it, now we have a reusable class which a designer could use to add “behavior” to our XamDataGrid.

Creating a custom panel using WPF

The Grid, StackPanel, WrapPanel and DockPanel are used to layout controls in WPF. All four are derived from the WPF Panel class. So if we want to create our own “custom panel” we obviously use the Panel as our starting point.

So to start with, we need to create a subclass of the Panel class in WPF. We then need to override both the MeasureOverride and ArrangeOverride methods.

public class MyCustomPanel : Panel
{
   protected override Size MeasureOverride(Size availableSize)
   {
      return base.MeasureOverride(availableSize);
   }

   protected override Size ArrangeOverride(Size finalSize)
   {
      return base.ArrangeOverride(finalSize);
   }
}

WPF implements a two pass layout system to both determine the sizes and positions of child elements within the panel.

So the first phase of this process is to measure the child items and find what their desired size is, given the available size.

It’s important to note that we need to call the child elements Measure method before we can interact with it’s DesiredSize property. For example

protected override Size MeasureOverride(Size availableSize)
{
   Size size = new Size(0, 0);

   foreach (UIElement child in Children)
   {
      child.Measure(availableSize);
      resultSize.Width = Math.Max(size.Width, child.DesiredSize.Width);
      resultSize.Height = Math.Max(size.Height, child.DesiredSize.Height);
   }

   size.Width = double.IsPositiveInfinity(availableSize.Width) ?
      size.Width : availableSize.Width;

   size.Height = double.IsPositiveInfinity(availableSize.Height) ? 
      size.Height : availableSize.Height;

   return size;
}

Note: We don’t want to return a infinite value from the available width/height, instead we’ll return 0

The next phase in this process is to handle the arrangement of the children using ArrangeOverride. For example

protected override Size ArrangeOverride(Size finalSize)
{
   foreach (UIElement child in Children)
   {
      child.Arrange(new Rect(0, 0, child.DesiredSize.Width, child.DesiredSize.Height));
   }
   return finalSize;
}

In the above, minimal code, we’re simply getting each child element’s desired size and arranging the child at point 0, 0 and giving the child it’s desired width and height. So nothing exciting there. However we could arrange the children in other, more interesting ways at this point, such as stacking them with an offset like a deck of cards or largest to smallest (or vice versa) or maybe recreate an existing layout but use transformation to animate their arrangement.

MahApps, where’s the drop shadow ?

In the MahApps Metro UI, specifically the MetroWindow we can turn the drop shadow on using the following. In code…

BorderlessWindowBehavior b = new BorderlessWindowBehavior
{
   EnableDWMDropShadow = true,
   AllowsTransparency = false
};

BehaviorCollection bc = Interaction.GetBehaviors(window);
bc.Add(b);

Note: We must set the Allow Transparency to false to use the EnableDWMDropShadow.

In XAML, we can use the following

<i:Interaction.Behaviors>
   <behaviours:BorderlessWindowBehavior 
      AllowsTransparency="False" 
      EnableDWMDropShadow="True" />
</i:Interaction.Behaviors>

Caliburn Micro, convention based binding

Caliburn Micro implements a convention based system for binding to “default” properties on controls and actions etc. This is on by default but can be switched off using ViewModelBinder.ApplyConventionsByDefault and setting this to false. You can also enable/disable conventions on a view-by-view basis by setting the attached property View.ApplyConventions to true in a view, for example (with other namespace etc. removed)

<UserControl x:Class="Sample.ShellView"
   xmlns:Micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
   Micro:View.ApplyConventions="False">

Let’s take a look at some basics of the convention based code.

In a view model class (assuming you’re derived from PropertyChangedBae) we can add the following code

private string fullName;

public string FullName
{
   get { return fullName; }
   set
   {
      if(fullName!= value)
      {
         fullName= value;
         NotifyOfPropertyChange(() => FullName);
      }
   }
}

Now, in the corresponding view add the following

<TextBox Name="FullName" />

Note the use of the name property and no binding property, this is because Caliburn Micro creates the link for us based upon the name and the binding property defined within it for mapping within Caliburn Micro (in other words, it’s binding based upon a naming convention).

For example the convention for a TextBox is that the binding property to be used is the Text property. Internally this looks like this

AddElementConvention<TextBlock>(TextBlock.TextProperty, "Text", "DataContextChanged");

We can, in fact, add our own convention based bindings for any controls not supported by default such as our own controls. For example, let’s create a convention based binding for a Rectangle object (which isn’t one of the default supported controls) whereby the convention based binding will look like this in XAML.

<Rectangle Width="100" Height="100" Name="Colour" />

and in our code (somewhere such as the top most view model or boostrapper) we would have something like this

ConventionManager.AddElementConvention<Rectangle>(Shape.FillProperty, "Fill", "FillChanged");

This will then create a binding from the name “Colour” on our viewmodel to the Fill property of the Rectangle (or Shape). Thus the Colour (obviously assuming it is a Brush) will be bound to the Fill property automatically.

The last argument in the AddElementConvention method is for the eventName and this can be used to use the same mechanism to fire commands on our view model.

Let’s add a Button to our code that looks like this, in XAML

<Button Name="Save" Content="Save" />

Now in the associated view model simply add the following code

public void Save()
{
}

It’s as simple as that to bind to the click event of the button. So, when the button is clicked the Save method on the view model is called. This is because of the following code, which Caliburn Micro

AddElementConvention<ButtonBase>(ButtonBase.ContentProperty, "DataContext", "Click");

One very useful bit of code in Caliburn Micro is for situations where you might wish to pass an argument to a method in a view model. Let’s assume that you have multiple save buttons on a form, one for draft save and one for full save (for want of a better example).

We want to use the same code on the view model to handle both saves, however depending on the argument pass to the method we will do a draft of full save. Maybe these two operations share a bunch of code so it suits us to reuse this code. Okay so it’s a slightly convoluted example, but you get the idea.

So our method will look like this

public void Save(string draftOrFull)
{
   // do a load of shared things

   if(draftOrFull == "draft")
   {
      // draft save
   }
   else if(draftOrFull == "save")
   {
      // full save
   }
}

Now add the following code to the XAML

<Button Content="Draft" cal:Message.Attach="[Event Click] = [Action Save('draft')]"/>
<Button Content="Save" cal:Message.Attach="[Event Click] = [Action Save('full')]"/>

The attached property Message.Attach will attach the Click event to the action “Save” passing the string draft or full – note the single quotes for the string.

We can achieve the same as above in a longer format as follows

<Button Content="Draft">
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="Click">
         <cal:ActionMessage MethodName="Save">
            <cal:Parameter Value="draft" />
         </cal:ActionMessage>
      </i:EventTrigger>
   </i:Interaction.Triggers>
</Button>