Archive

Archive for the ‘.NET 4’ Category

Of Mice and Men and Computed Observables. Oh my.

November 21, 2012 15 comments

I have recently been playing around with Knockout.js, and have been hugely impressed with just how clever it is, and how intuitive. One of the really great features that Knockout provides is the ability to have a computed observable object. That’s a fancy way of saying that it has functionality to update when objects that it is observing update. Borrowing an example from the Knockout website, this simply translates into code like this:

function AppViewModel() {
    this.firstName = ko.observable('Bob');
    this.lastName = ko.observable('Smith');
 
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
}

So, whenever firstName or lastName change, the fullName automatically changes as well.

Wouldn’t it be great if we could do this in WPF as well? I would love it if MVVM allowed you to update one property and have all dependent properties update with it – currently, if you have a dependent property then you have to update that manually.

Well, Dan Vaughan has an amazing implementation of this functionality over on his site, and it’s quite astounding code – he really does have the brain the size of a planet. Being a simpler person though, I had to wonder if there was a simpler way that didn’t involve rewriting a lot of old ViewModels, and the word that kept coming to my mind is MarkupExtension. For those of you who don’t know what a MarkupExtension is, it’s a way to let XAML know that it has something to do that’s a little bit special – you’ve probably already used some even without knowing it – if you’ve used StaticResource, DynamicResource or Binding then you’ve used a MarkupExtension.

So, having thought it through from a few different angles, it seemed as though a MarkupExtension will do the job – and surprise surprise, it does. Before I go into the code, though, I’m going to share some code with you that you will definitely find handy if you write your own extensions that rely on the DataContext. Basically, because of the different places and ways you can declare a DataContext, I wanted some code that I could use to cope with the DataContext not being present when we fired off our extension.

So, let’s break down that extension first. Unsurprisingly, we’re going to make this an abstract extension, as it’s not much use on its own – it’s a great way to support other extensions, but it does nothing useful that we’d want to hook into in the XAML:

public abstract class DataContextBaseExtension : MarkupExtension

If you notice, we are inheriting from MarkupExtension – this is vital if we want to be able to use this as an extension. Now, by convention, extensions always end in Extension, but we don’t have to include that when we declare it in the XAML. Even though we don’t directly use this class in XAML, it’s good to name it this way so that we preserve the intent.

Next, we are going to declare some properties that we will find useful later on.

/// <summary>
/// Gets or sets the target object from the service provider
/// </summary>
protected object TargetObject { get; set; }

/// <summary>
/// Gets or sets the target property from the service provider
/// </summary>
protected object TargetProperty { get; set; }

/// <summary>
/// Gets or sets the target Dependency Object from the service provider
/// </summary>
protected DependencyObject TargetObjectDependencyObject { get; set; }

/// <summary>
/// Gets or sets the target Dependency Property from the service provider;
/// </summary>
protected DependencyProperty TargetObjectDependencyProperty { get; set; }

/// <summary>
/// Gets or sets the DataContext that this extension is hooking into.
/// </summary>
protected object DataContext { get; private set; }

Don’t worry about what they do yet – we’ll cover them more as we examine the code. Assigning these properties is taken care of in the overriden MarkupExtension.ProvideValue implementation:

/// <summary>
/// By sealing this method, we guarantee that the developer will always
/// have to use this implementation.
/// </summary>
public sealed override object ProvideValue(IServiceProvider serviceProvider)
{
    IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

    if (target != null)
    {
        TargetObject = target.TargetObject;
        TargetProperty = target.TargetProperty;

        // Convert to DP and DO if possible...
        TargetObjectDependencyProperty = TargetProperty as DependencyProperty;
        TargetObjectDependencyObject = TargetObject as DependencyObject;

        if (!FindDataContext())
        {
            SubscribeToDataContextChangedEvent();
        }
    }

    return OnProvideValue(serviceProvider);
}

As you can see, assigning these values is straight forward, but we start to see the meat of this class now. By sealing this method, we ensure that we cannot override it (giving us a stable base for this class – we can’t accidentally forget to call this implementation), which means that we have to provide a way for derived classes can do any processing that they need as well. This is why we return an abstract method that derived classes can hook into to do any further processing:

protected abstract object OnProvideValue(IServiceProvider serviceProvider);

Now, this method is only fired once, which means the DataContext could be set long after this code has finished. Fortunately, we can get round this by hooking into the DataContextChanged event.

private void SubscribeToDataContextChangedEvent()
{
    DependencyPropertyDescriptor.FromProperty(FrameworkElement.DataContextProperty, 
        TargetObjectDependencyObject.GetType())
        .AddValueChanged(TargetObjectDependencyObject, DataContextChanged);
}

But how do we actually find the DataContext? Well, this is straightforward as well

private void DataContextChanged(object sender, EventArgs e)
{
    if (FindDataContext())
    {
        UnsubscribeFromDataContextChangedEvent();
    }
}

private bool FindDataContext()
{
    var dc = TargetObjectDependencyObject.GetValue(FrameworkElement.DataContextProperty) ??
        TargetObjectDependencyObject.GetValue(FrameworkContentElement.DataContextProperty);
    if (dc != null)
    {
        DataContext = dc;

        OnDataContextFound();
    }

    return dc != null;
}

private void UnsubscribeFromDataContextChangedEvent()
{
    DependencyPropertyDescriptor.FromProperty(FrameworkElement.DataContextProperty, 
         TargetObjectDependencyObject.GetType())
        .RemoveValueChanged(TargetObjectDependencyObject, DataContextChanged);
}

The only things of any real note in there is that, once the DataContext is found in the event handler, we disconnect from the DataContextChanged event and call an abstract method to let derived classes know that the DataContext is has been found.

protected abstract void OnDataContextFound();

Right, that’s our handy DataContextBaseExtension class out the way (hold onto it – you might find it useful at some point in the future). Now let’s move onto the extension that does the markup mojo. This class adheres to the convention of ending in Extension:

public class ComputedObservableExtension : DataContextBaseExtension

Now, we want to provide the ability for the user to use a parameter name, or to have one automatically applied if we leave it out. You’ve seen this behaviour when you’ve done {Binding Name} or {Binding Path=Name}. In both cases, Path was being referred to, but MarkupExtensions are clever enough to work this out. To do this, we need to supply two constructors, and use something called a ConstructorArgument to tell the extension that a particular property is being defaulted.

public ComputedObservableExtension()
    : this(string.Empty)
{

}

public ComputedObservableExtension(string path)
    : base()
{
    this.Path = path;
}

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

We are going to use Path to refer to the computed property. We also need something to tell the extension what properties we are going to observe the change notification on:

public string ObservableProperties
{
    get;
    set;
}

I’m not being fancy with that list. In this implementation, you simply need to supply a comma separated list of properties to this method. Now we are going to hook into the override OnProvideValue method to do a little bit of processing at the startup of this class.

protected override object OnProvideValue(IServiceProvider serviceProvider)
{
    if (TargetProperty != null)
    {
        targetProperty = TargetProperty as PropertyInfo;
        
    }

    if (!string.IsNullOrWhiteSpace(ObservableProperties))
    {
        string[] observables = ObservableProperties
            .Replace(" ", string.Empty)
            .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

        if (observables.Count() > 0)
        {
            observedProperties.AddRange(observables);

            // And update the property...
            UpdateProperty(ComputedValue());
        }
    }

    return string.Empty;
}

Basically, we start off by caching the TargetProperty as a PropertyInfo. We’ll make heavy use of this later on, so it removes a bit of reflection burden if we already have the PropertyInfo at this point. Next, we split the list of observed properties up into a list that we will use later on. The UpdateProperty method is used to actually update the computed property on the screen, so let’s take a look at that next.

private void UpdateProperty(object value)
{
    if (TargetObjectDependencyObject != null)
    {
        if (TargetObjectDependencyProperty != null)
        {
            Action update = () => TargetObjectDependencyObject
                .SetValue(TargetObjectDependencyProperty, value);

            if (TargetObjectDependencyObject.CheckAccess())
            {
                update();
            }
            else
            {
                TargetObjectDependencyObject.Dispatcher.Invoke(update);
            }
        }
        else
        {
            if (targetProperty != null)
            {
                targetProperty.SetValue(TargetObject, value, null);
            }
        }
    }
}

As you can see, this code simply sets the value – either using the DependencyProperty and DependencyObject that we first obtained in the base class, or by updating the standard property if the DP isn’t present.

The ComputedValue method is responsible for retrieving the value from the underlying DataContext.

private string ComputedValue()
{
    if (DataContext == null) return string.Empty;
    if (string.IsNullOrWhiteSpace(Path)) throw new ArgumentException("Path must be set");

    object value = GetPropertyInfoForPath().GetValue(DataContext, null);

    if (value == null)
        return string.Empty;
    return value.ToString();
}

private PropertyInfo propInfo;

private PropertyInfo GetPropertyInfoForPath()
{
    if (propInfo != null) return propInfo;

    propInfo = DataContext.GetType().GetProperty(Path);
    if (propInfo == null) throw new InvalidOperationException(string.Format("{0} is not a valid property", Path));

    return propInfo;
}

We seem to be missing a bit though. If you thought that, you would be right – the bit that’s missing is what happens when we find the DataContext. Well, when we have a DataContext, we use the fact that it’s implemented INotifyPropertyChanged to our own advantage.

protected override void OnDataContextFound()
{
    if (DataContext != null)
    {
        propChanged = DataContext as INotifyPropertyChanged;
        if (propChanged == null) 
            throw new InvalidOperationException("The data context item must support INotifyPropertyChanged");

        UpdateProperty(ComputedValue());

        if (TargetObject != null)
        {
            ((FrameworkElement)TargetObject).Unloaded += ComputedObservableExtension_Unloaded;
        }
        propChanged.PropertyChanged += propChanged_PropertyChanged;
    }
}

void ComputedObservableExtension_Unloaded(object sender, RoutedEventArgs e)
{
    if (TargetObject != null)
    {
        ((FrameworkElement)TargetObject).Unloaded -= ComputedObservableExtension_Unloaded;
    }
    propChanged.PropertyChanged -= propChanged_PropertyChanged;
}

void propChanged_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (observedProperties.Count == 0 || string.IsNullOrWhiteSpace(e.PropertyName) || 
      observedProperties.Contains(e.PropertyName))
    {
        UpdateProperty(ComputedValue());
    }
}

And that’s pretty much it – that’s all we need to give the XAML the markup that we wanted.

But, what does our MVVM code look like now? Well, let’s start with a familiar POCO VM:

public class PersonViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string firstName;
    private string surname;
    private int age;

    public string Firstname
    {
        get { return firstName; }
        set
        {
            if (firstName == value) return;
            firstName = value;
            Notify("Firstname");
        }
    }

    public string Surname
    {
        get { return surname; }
        set
        {
            if (surname == value) return;
            surname = value;
            Notify("Surname");
        }
    }

    public int Age
    {
        get { return age; }
        set
        {
            if (age == value) return;
            age = value;
            Notify("Age");
        }
    }

    public string Details
    {
        get
        {
            return firstName + " " + surname + " is " + age.ToString();
        }
    }

    private void Notify(string prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler == null) return;

        handler(this, new PropertyChangedEventArgs(prop));
    }
}

Now, let’s attach it to our main window.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private PersonViewModel person;
    public MainWindow()
    {
        InitializeComponent();
        person = new PersonViewModel { Age = 21, Firstname = "Bob", Surname = "Smith" };
        DataContext = person;
    }
}

As you can see – we’ve put no magic in here. It’s just a simple VM. So, what does the XAML look like?

<Window x:Class="ComputedObservableExtensionExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:co="clr-namespace:ComputedObservableExtensionExample"
        Title="Computed ObservableExample" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontSize" Value="13.333" />
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="FontSize" Value="13.333" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="Margin" Value="2" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>
        
        <TextBlock Text="Firstname" Grid.Row="0" Grid.Column="0" />
        <TextBlock Text="Surname" Grid.Row="1" Grid.Column="0" />
        <TextBlock Text="Age" Grid.Row="2" Grid.Column="0" />

        <TextBox Text="{Binding Firstname, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1" />
        <TextBox Text="{Binding Surname, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1" />
        <TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1" />

        <TextBlock Text="{co:ComputedObservable Details, 
            ObservableProperties='Firstname,Surname,Age'}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" />
    </Grid>
</Window>

And that’s it – the TextBlock with the ComputedObservable extension has been told that the Path is the Details property, and the properties that it’s observing are Firstname, Surname and Age – so changing any of those properties results in the computed property being updated as well.

Any comments, enhancements or observations, please feel to let me know. This is a first pass at this extension, and I’ve no doubt that I will be revisiting and enhancing it as I use it more and more. I will, of course, come back here and update this post as I do so.

Note – this project is a VS2012 solution, but it does not make use of any .NET 4.5 specific features, so you should be able to use the code in a VS2010 app.

Source is available here. Examplezip

Scratching that old itch.

February 11, 2011 Leave a comment

First of all, I must apologise that it’s been so long since I last blogged. It’s been an insanely busy time for me (and I don’t mean that I’ve been coding with my underpants on my head). As you may be aware, I’m a big fan of Blend behaviours, so I thought that I’d take the time to revisit an old favourite of mine. To that end, I present all the code you’ll need to create a watermarked textbox.

namespace Goldlight.Extensions.Behaviors
{
  using System.Windows.Interactivity;
  using System.Windows.Controls;
  using System.Windows.Media;
  using System.Windows;

  public class WatermarkTextBoxBehavior : Behavior<TextBox>
  {
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.LostFocus += new RoutedEventHandler(LostFocus);
      AssociatedObject.GotFocus += new RoutedEventHandler(GotFocus);
      SetWatermark();
    }

    protected override void OnDetaching()
    {
      base.OnDetaching();
      AssociatedObject.LostFocus -= new RoutedEventHandler(LostFocus);
      AssociatedObject.GotFocus -= new RoutedEventHandler(GotFocus);
    }
    /// <summary>
    /// Get or set the brush to use as the foreground.
    /// </summary>
    public Brush WatermarkForeground { get; set; }
    /// <summary>
    /// Get or set the brush to use as the background.
    /// </summary>
    public Brush WatermarkBackground { get; set; }
    /// <summary>
    /// Get or set the text to apply as the watermark.
    /// </summary>
    public string WatermarkText { get; set; }

    /// <summary>
    /// Reset the colours of the textbox.
    /// </summary>
    private void SetStandard()
    {
      AssociatedObject.ClearValue(TextBox.ForegroundProperty);
      AssociatedObject.ClearValue(TextBox.BackgroundProperty);

      if (AssociatedObject.Text == WatermarkText)
      {
        AssociatedObject.Text = string.Empty;
      }
    }
    /// <summary>
    /// Set the watermark colours for the textbox.
    /// </summary>
    private void SetWatermark()
    {
      if (WatermarkForeground != null)
      {
        AssociatedObject.Foreground = WatermarkForeground;
      }
      if (WatermarkBackground != null)
      {
        AssociatedObject.Background = WatermarkBackground;
      }
      AssociatedObject.Text = WatermarkText;
    }
    void GotFocus(object sender, RoutedEventArgs e)
    {
      SetStandard();
    }
    void LostFocus(object sender, RoutedEventArgs e)
    {
      CheckText(AssociatedObject.Text);
    }
    private void CheckText(string value)
    {
      if (string.IsNullOrWhiteSpace(value))
      {
        SetWatermark();
      }
      else
      {
        SetStandard();
      }
    }
  }
}

The code is pretty straightforward. When the textbox receives focus, if it contains just the Watermark text, the watermark text is cleared out and the original foreground and background brushes are restored. When the textbox loses focus, if it’s empty the watermark text is displayed and the watermark fore and background brushes are set. Now, for the clever bit, because we’re updating the textbox text directly we aren’t going to be updating any underlying binding

Faster faster loops

May 3, 2010 6 comments

With multicore machines becoming more and more commonplace, it’s madness that loops can’t take use of this extra grunt. Fortunately for us, those nice guys and girls at Microsoft share our frustration with this state of affairs and have taken steps to give us loop capabilities that can take advantage of this extra capacity.

Prompted by a question on Code Project, I’d like to show a quick code sample that demonstrates a new feature in .NET 4.0 called the Task Parallel Library. With this library, it is much easier to write code in a managed language that makes use of multiple cores where available. This gives us the option to write code as parallel tasks that are run concurrently across available processors; generally resulting in significantly speeded up code.

Here’s a sample of the code that we are going to parallelize:

using System;

namespace ParallelForSample
{
  public class SingleCore
  {
    public static void Calculate(int calcVal)
    {
      // Utility contains references to stopwatch which
      // we use to display details about the time taken
      // to run this code.
      Utility util = new Utility();
      util.Start();

      int[,] G = new int[calcVal, calcVal];
      for (int k = 0; k < calcVal; k++)
        for (int i = 0; i < calcVal; i++)
          for (int j = 0; j < calcVal; j++)
            G[i, j] = Math.Min(G[i, j], G[i, k] + G[k, j]);
      util.Stop();

    }
  }
}

As you can see, this is a fairly straightforward class – it’s got three loops which are used to populate an array. Now, here’s the code rewritten to use the TPL:

using System;
using System.Threading.Tasks;

namespace ParallelForSample
{
  public class MultiCore
  {
    public static void Calculate(int calcVal)
    {
      Utility util = new Utility();
      util.Start();

      int[,] G = new int[calcVal, calcVal];

      Parallel.For(0, calcVal,
        delegate(int k)
        {
          Parallel.For(0, calcVal, delegate(int i)
          {
            for (int j = 0; j < calcVal; j++)
              G[i, j] = Math.Min(G[i, j], G[i, k] + G[k, j]);
          });
        }
      );

      util.Stop();
    }
  }
}

As you can see, the syntax is slightly different. The for loop is broken down into Parallel.For. It takes a delegate which actually performs the loop behaviour. If you download the sample and run it, you can observe the difference in behaviour and timings of the loops. Now, the difference will only be observed if you have a multiple core machine; if you don’t the loop will behave as though it’s running on a single core.

Link: parallelforsample.zip

Note: As always, when downloading from here, please rename the file so that it doesn’t end in .doc.

The Canny Coder

Java 8 Functional Programming with Lambda Expressions

pihole.org

Adventures in theoretical computer science, with your host, chaiguy1337

Confessions of a coder

Confessions of a WPF lover

WordPress.com

WordPress.com is the best place for your personal blog or business site.

Follow

Get every new post delivered to your Inbox.

Join 39 other followers