Skip Navigation LinksHome
DotNetDevNet: Xamlathon Live '10

Last night I presented for the DotNetDevNet group at the University of West England. The title of my talk was Xamlathon Live '10 - mostly a bunch of tips for Expression Blend.

It was great fun - I really love presenting for this group. They're a great bunch and I always enjoy going for a beer afterwards.

As promised - here are the bits and pieces from the presentation:

The last demo blew due to a silly typo but I managed to fix it before everyone went home (but after they'd completed their evals!). The reason for the break was a typo in my AnimateValue user control that manually applies the animation. The commented line shows what it *should* be:

private void ValueChanged()
{
    DoubleAnimation da = new DoubleAnimation();
    da.To = this.Value;
    da.EasingFunction = new BackEase();
    da.Duration = new Duration(TimeSpan.FromMilliseconds(300));
    Storyboard sb = new Storyboard();
    Storyboard.SetTarget(da, this.ProgressBar);
    // A good case for not calling controls by their class name? This is what it *should* have said:
    //    Storyboard.SetTargetProperty(da, new PropertyPath(ProgressBar.ValueProperty));
    Storyboard.SetTargetProperty(da, new PropertyPath(ProgressBar.Value));
    sb.Children.Add(da);
    sb.Begin();
}

This was easily spotted by running the project under the Visual Studio debugger which took me right to the erroneous line. Another tip (Bing!).

Now, for the 'deal' I talked about. If, enough of you express an interest by leaving a comment below - I'll work the whole session into a series of blog posts that walk you through the entire demo step by step. This will take a lot of my time and therefore I want to be sure there's enough interest to warrant it.

Thanks again

Josh Post By Josh Twist
4:55 AM
21 Jan 2010
Silverlight, MVVM and Validation Part III

I've been working with Silverlight 3 in a number of LoB (Line of Business) scenarios for a while now and I'm consistently running in to a few dead ends with respect to Validation. Given I've posted twice before on Silverlight, MVVM and Validation:

I thought it only right to point out some of the shortcomings of these approaches and Silverlight 3 itself. The problem arises from the exciting, great-looking, new Validation states supported on some of the common input controls:

SL3 Validation

However, the only way to get a control into an 'invalid state' is to throw an exception in a bound setter. This is the key problem and leads to a number of inconsistencies as to how one should deal with validation, e.g.:
  1. If an exception is thrown within a setter then the property’s value should not be updated. This means that the bound object is still actually in a valid state and the controller (e.g. code-behind, presenter or viewmodel) has no visibility that the UI and bound model are now inconsistent, or that the UI is in an invalid state (because the model is still valid).
  2. When a TypeConverter fails to convert input for a binding, a similar problem to one described above arises – the model never receives the input and therefore the validation issue is unknown to the model (I tried to work-around these problems with limited success in this post: http://www.thejoyofcode.com/Silverlight_Validation_and_MVVM_Part_II.aspx - however, this falls flat in the face of cross-property validation).
  3. Throwing exceptions in property setters means we can’t bind to many generated models (e.g. WCF proxy types) as there is no way we can insert this logic into the generated type (no partial methods etc).
  4. Custom types that throw exceptions in setters can make cross-field validation very difficult (nay impossible, practically speaking). Furthermore, this approach may cause further difficulty for the framework in deserializing such a type depending on the order in which properties are set (e.g. Salutation and Gender could cause a failure during deserialization if the two aren’t in sync as the properties are set). Trying to work around these issues creates horrific spaghetti validation code that is best avoided altogether.
In consideration of the above, I've occasionally decided to abandon the cool new validation states in SL3 altogether in favour of something custom. I tried to invoke these states manually but was blocked:
  • You can manually trigger the change of visual state [e.g: VisualStateManager.GoToState(MyTextBox, “InvalidFocussed”, true); ]. The internal operation and flip between focussed and infocussed state appears to hang off a private _isInvalid member of the Control class – blocking the developer from working with the validation framework.
  • Even if we could overcome these issues, this behaviour invokes a template that binds directly to the Validation.Errors attached property for the tooltip. However, Validation.Errors is a read-only collection and the AddValidationError method is internal. Furthermore, the actual type ValidationError has an internal constructor. So all routes are blocked as far as I can see.
Whilst I love Silverlight the validation story in Silverlight 3 is somewhat incomplete with respect to the new Validation States that ship with the controls. However, forewarned is forearmed so think carefully before relying on the Silverlight 3 validation features if your validation requirements are anything more then very, very simple.

The good news

... is, that there is better support for Validation in Silverlight 4 (available in Beta at the time of writing). This is thanks to added support for the IDataErrorInfo interface which I have written about before with respect to its being supported inside WPF.

Based on the example in the previous post in this 'series': Silverlight, Validation and MVVM - Part II, here's an example of how you might implement this interface. I've chosen to do it this way because I'm a big ViewModel fan and already have a base class to which adding some validation logic seems to make sense. Additionally, I want to leverage the ValidationAttributes available in RIA services (even if I'm not using RIA services themselves). Ideally, the attributes could just be added to the 'model' properties without anymore work. And that's what I've shot for with my new base class.

Firstly, to manage this and return the results in the appropriate format I've created a ValidationManager class:

public class ValidationManager
{
    private readonly INotifyPropertyChanged _instance;
    private bool _isDirty = true;
    private readonly ValidationResultCollection _results = new ValidationResultCollection();

    public ValidationManager(INotifyPropertyChanged instance)
    {
        if (instance == null)
            throw new ArgumentNullException("instance");
        _instance = instance;
        _instance.PropertyChanged += delegate
            {
                _isDirty = true;
            };
    }

    public ValidationResultCollection Results
    {
        get
        {
            if (_isDirty)
            {
                Validate();
                _isDirty = false;
            }
            return _results;
        }
    }

    public ValidationResultCollection ResultsForMemberName(string memberName)
    {
        var results = Results.Where(r => r.MemberNames.Contains(memberName));
        return new ValidationResultCollection(results);
    }

    private void Validate()
    {
        _results.Clear();
        Validator.TryValidateObject(_instance, new ValidationContext(_instance, null, null), _results, true);
    }
}

public class ValidationResultCollection : List<ValidationResult>
{
    public ValidationResultCollection()
    : base()
    { }

    public ValidationResultCollection(IEnumerable<ValidationResult> results)
    : base(results)
    { }

    public override string ToString()
    {
        if (this.Count == 0)
        {
            return null;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < this.Count; i++)
        {
            sb.Append(this[i]);
            if (i < this.Count - 1)
            {
                sb.AppendLine();
            }
        }
        return sb.ToString();
    }
}

This class simply helps me to implement IDataErrorInfo by storing validation results and ensuring they're only re-generated if the object is 'dirtied' (we observe the INotifyPropertyChanged instance so we can know this). The validation results are then created on demand for the whole object (to ensure any class-level validators are invoked).

Next, I created my base class (based on my BaseViewModel from my snippets).

public class ValidatingViewModelBase : INotifyPropertyChanged, IDataErrorInfo
{
    private readonly ValidationManager _validationManager;

    public ValidatingViewModelBase()
    {
        _validationManager = new ValidationManager(this);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler pceh = PropertyChanged;
        if (pceh != null)
        {
            pceh(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected virtual bool SetValue<T>(ref T target, T value, params string[] changedProperties)
    {
        if (Object.Equals(target, value))
        {
            return false;
        }

        target = value;

        foreach (string property in changedProperties)
        {
            OnPropertyChanged(property);
        }

        return true;
    }

    public string Error
    {
        get { return _validationManager.Results.ToString(); }
    }

    public string this[string columnName]
    {
        get
        {
            return _validationManager.ResultsForMemberName(columnName).ToString();
        }
    }
}

Now I just have to implement my model by inheriting from this class. And the best bit is I can just use attributes to apply validation logic to my type. Nice:

public class Person : ValidatingViewModelBase
{
    private string _name;

    [Required(ErrorMessage = "Name is required")]
    public string Name
    {
        get { return _name; }
        set
        {
            SetValue(ref _name, value, "Name");
        }
    }

    private string _salutation;

    [Required(ErrorMessage = "Salutation is required")]
    public string Salutation
    {
        get { return _salutation; }
        set
        {
            SetValue(ref _salutation, value, "Salutation");
        }
    }

    private int _age;

    [Required(ErrorMessage = "Age is required")]
    [Range(18, int.MaxValue, ErrorMessage = "Must be over 18")]
    public int Age
    {
        get { return _age; }
        set
        {
            SetValue(ref _age, value, "Age");
        }
    }
}

And here's a demo for you to try:

And, even to my own surprise, this works remarkably well. You can even add new objects and the validation invokes nicely!

but...

There are however, a couple of problems.

If the binding engine can't convert your input to the ViewModel type (for example, try inputting some nonsense string into the Age field above); then the view will display a notification (thank to ValidatesOnExceptions=true) but the ViewModel will be unaware of this failing and you won't be able to prevent the update going ahead. For this reason, I'd strongly recommend a hybrid approach utilising the ValidationScope from the previous post to capture Binding Errors and report them to the ViewModel. Note, I haven't included this in the sample above and, instead, have left that as an exercise for the reader.

The other problem to be aware of is silent conversion success. That is, if you enter 21.322 into the Age field then the binding will succeed. But, because that field is bound to an Int32, some of your data will be lost. As far as I know, there is now way to know this is happening so you'd have to implement something at the view to deal with this in a more sophisticated way (a new, derived TextBox control maybe?).

I've always felt IDataErrorInfo to be an 'immature' interface - it feels as though it's from a bygone era. Somebody in Redmond obviously feels the same and Silverlight 4 introduces a new INotifyDataErrorProperty which feels more elegant. The code above should modify to support this new interface with relative ease. Have a read of Mike Taulty's excellent posts on both interface for more information:

The source code for the example is available below. Please note that this is demoware - I'm posting ideas, not fully-furnished-frameworks-cum-mega-solutions. As always, your own mileage may vary.

Josh Post By Josh Twist
11:47 AM
15 Jan 2010
The Binding you wanted from day one in WPF

Remember when you started playing with WPF? Remember when you coded your first binding?

{Binding ElementName=slider, Path=Value}

and then remember what you wanted to do next? Something like this I'm sure...

{Binding ElementName=slider, Path=Value/2}

(in case you missed it, I'm trying to divide Value by 2). At least I know I've always yearned for basic expression support in WPF bindings. Converters have always allowed you to do this but I've always found the process of creating a converter really interrupts my flow. I've since found ways to partly reduce the friction when using Converters but I'd be happier if I could just have support for expressions.

Long term readers of this blog will remember I'm a big fan of dynamic compilation and, particularly, Expressions which make Dynamic Compilation much easier. And so my idea for a Binding/Converter that supports expressions was born. And here it is:

<Slider x:Name="slider" />
<TextBlock Text="{Binding ElementName=slider, Path=Value, Converter={binding:ExpressionConverter Expression=x/2, InputType=sys:Double, Cache=true}}" />

Or, using the shorter syntax (assuming default values for InputType (double) and Cache (true):

<Slider x:Name="slider" />
<TextBlock Text="{Binding Value, ElementName=slider, Converter={binding:ExpressionConverter x/2}}" />

Nice! How does this work?

Shipping with the Visual Studio 2008 C# samples (available on MSDN Code Gallery) was a rather neat file called Dynamic.cs that contains a neat type called System.Linq.Dynamic.DynamicExpression (not to be confused with the DynamicExpression type that will ship with .NET 4.0).

This supports the parsing of LambdaExpressions as shown below:

ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(double), "x");

var exp = DynamicExpression.ParseLambda(
    new ParameterExpression[] { x },
    null,
    "x/2");

var func = (Func<double,double>)exp.Compile();

Console.WriteLine(func(5));

Saweet. This little program would dump '2.5' to the Console window. Nice (I was about to start writing my own Exprssion parsing algorithm so thanks to my colleagues Zulfiqar Ahmed and James World for introducing me to this little gem).

This is the key piece of magic but you can download the source (below) to get a full view of the current implementation.

More examples

The reason the InputType defaults to double is because I imagine that the vast majority of times you'll want to use this for some basic layout magic (ActualWidth / 2 etc). However, there are many scenarios where you may wish to change the InputType. For example, imagine we have a type called Item with two DateTime properties, CreatedDate and ModifiedDate:

// TODO - for brevity I haven't implemented INotifyPropertyChanged
public class Item
{
    public string Name { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime ModifiedDate { get; set; }
}

And we might have a list of these items bound to an ItemsSource:

<ListBox ItemsSource="{Binding}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}" />
                <TextBlock Text="{Binding CreatedDate, StringFormat='Created: {0:yyyy-MM-dd} '}" VerticalAlignment="Bottom" FontSize="10" />
                <TextBlock Text="{Binding ModifiedDate, StringFormat='Modified: {0:yyyy-MM-dd} '}" VerticalAlignment="Bottom" FontSize="10" />
                <TextBlock x:Name="NewText" Text=" NEW!" Foreground="Red" FontWeight="Bold" Visibility="Collapsed" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

And imagine we would like to highlight 'NEW' items, i.e. those where the ModifiedDate is equal to the CreatedDate and were created in the last week. Easy with the ExpressionConverter and a DataTrigger added to our DataTemplate:

<DataTrigger
    Binding="{Binding Converter={binding:ExpressionConverter 'x.CreatedDate == x.ModifiedDate &amp;&amp; Datetime.Now.AddDays(-7) &lt; x.ModifiedDate', InputType={x:Type local:Item}}}"
    Value="True">
    <Setter TargetName="NewText" Property="UIElement.Visibility" Value="Visible" />
</DataTrigger>

Note, that in this case we have to specify the InputType. Also, we had to encode ampersand and less than in XML. So, did it work? Of course:

ListBox with NEW items highlighted

Performance

So, how does this stuff perform?

Well, not bad actually. The compilation of the expression is relatively slow but this only happens once per converter. Of course, experienced WPFers will know this could easily lead to terrible performance as, if within an DataTemplate used by an ItemsControl, the converter might be created hundreds of times, ouch!

This is why the ExpressionConverter has a Cache property which defaults to true. When Caching is on, compiled expressions are cached in a static dictionary and a matching expression (based on the Expression string and InputType) will always reuse this compiled expression. Note, if you have many different expressions. That is, the expressions are being generated at runtime, then you might leak memory and therefore may choose not to use the cache. Set the Cache property to false if you're worried about this - you will then incur a compilation per Converter. The solution here is to put the Converter high in the resource tree so it's only compiled once and used as a resource wherever needed:
    
<Application.Resources>
    <binding:ExpressionConverter x:Key="SinConverter" Expression="Math.Sin(x)" Cache="false"/>
</Application.Resources>

Anyway, time for some rough figures about the speed of the expression itself. Here are the results for a million invocations of a reasonably complex Expression, "Math.Cos(x)/22+1/x":

Performance of ExpressionBinding

The results you're interested in are the direct invoke and wrapped invoke. direct invoke (which took 269ms for a million invocations) is the same 'expression' as a raw function being invoked directly (note it included conversion to a double as required by an IValueConverter which takes an object parameter). The wrapped invoke represents the dynamically compiled expression also including the converstion to a double. This took 371ms for a million invocations. So it's slower, no suprise, but by a factor of about .3 in this test.

I should point out that, in some tests, the dynamic binding exhibited slower invocations of up to 4x but this really isn't the point. In most cases this performance would be more than adequate as the calculation of the expression (and the addition of the dynamic slowness) which totals a miniscule ~0.0004ms, clearly isn't going to be the bottleneck in your application's peformance. However, for performance sensitive scenarios where you might have thousands of ExpressionBindings, within an ItemsControl for example, you may want to skip this and go the old fashioned way and use a normal Binding and custom IValueConverter.

Download

Usual disclaimers apply and as always - your own mileage may vary.

Tags: C# WPF

Josh Post By Josh Twist
5:13 AM
07 Jan 2010
The Future of Programming

There's been a lot of buzz about this article recently: Microsoft's Top Developer Prefer Old School Coding Methods.

I will fight you if you try to take away my text editor," said Don Box, a Microsoft distinguished engineer

"Do people want to draw pictures to program? Sure, I guess," continued Box, who works on creating declarative languages and tools for Microsoft. "But if you grew up programming when I did, you did it in text. And I think we lose that at our peril."

"Graphical programming environments are usable when they are useless, but unusable when they would be useful," said Jeffrey Snover, another Microsoft distinguished engineer and creator of Microsoft's PowerShell scripting tool for Windows. "When there are five things on the screen, you can burp that out. But when there are 500 things, graphical programming is completely unusable. You zoom in and zoom out and you lose all context. I think it's just smokin' dope."

Surprisingly, to me at least, this article got a mixed reaction. Personally I've always embraced this notion, specifically, that Visual Modelling isn't how I'd want to code. I previously suggested I'm not even that attached to creating UIs with a visual modelling tool (in If you can't beat XAML, improve it)!

When programming, a developer is communicating his intent to the computer and we communicate best through language. We're really good at text and language - we start practising at an early age and most of us are fluent in a couple of protocols - mine include English (just), C#, XAML and a tiny weeny bit of German (un peu :D). Language seems the most natural way to communicate and there aren't many examples where this isn't the case in the non-computing world either, with physical engineering drawings being the most notable exception.

So why don't we code in English? There can be no room for interpretation or ambiguity in computer code. Computers don't do ambiguity. We have the same challenge in the legal profession who do 'code' in their mother tongue. But the output here, legal documents and terms and conditions are ridiculously verbose. Therefore, in my opinion, what we have in code is a short-hand for very clearly stating our intent without ambiguity. This works great for me and I wouldn't swap that for visual modelling.

I should be clear that I'm not saying we're done. I think there's lots of room for improvements to languages and runtimes.

In terms of my development productivity, I believe the biggest thing holding me back right now is the physical human computer interface, not the languages. I dream of a time when speech recognition is good enough that I don't need my keyboard when coding anymore (although noise in a busy office might be a new problem). Languages would need to be optimised for this new input type and other NUI (natural user interface) ideas would need to mature as well (touch, eye tracking) to support this concept but that's where I think the big gains are to be made for developers. Not visual models.

Imagine being told that, from today, you can only communicate with your colleagues through the medium of drawings. No thanks. Don't get me wrong, I am never happier than when I'm in front of a whiteboard but the illustrations are only there to support and reinforce what I'm actually saying, which is nearly always in words ;)

Tags: Programming C#

Josh Post By Josh Twist
12:27 PM
05 Jan 2010
The SOA Manifesto

Sometimes, you hear a statement that resonates and reduces your thinking and makes you wish "why didn't I write that?".

I got a mail recently from P&P's John deVadoss (not just to me sadly, to a whole distribution of folk in MS ;). John was introducing the SOA Manifesto which is similar to the Agile Manifesto and a very welcome idea in my opinion.

All too often I see architects and developers terrified by Services and Service Orientation because they're not sure about their SOA governance strategy, taxonomy or colonoscopy (not sure about that last one). This is one of the best examples of throwing the baby out with the bath water that I know of.

When it comes to SOA I've always been of the opinion that you should "Just do it". Don't make the decision to build yet another non-integratable, black-walled system simply because you're scared of this stuff. You won't know what the future problems are until you run into them, but that doesn't mean you can't derive benefit from Services in the mean time. In short, these are good problems to have - it means your Services strategy is working but needs optimising. That's fantastic! If you do nothing, you get nothing.

However, "Just do it" makes me sound cavalier and like a bit of a cowboy. "Just do it" is a phrase that turns CIOs and infrastruture architects a very pale colour. Instead I much prefer some of the points on the SOA Manifesto:

  • Business value over technical strategy
  • Strategic goals over project-specific benefits
  • Intrinsic interoperability over custom integration
  • Shared services over specific-purpose implementations
  • Flexibility over optimization
  • Evolutionary refinement over pursuit of initial perfection
The two that resonate most for me are:
  • Business value over technical strategy
  • Evolutionary refinement over pursuit of initial perfection
So, Just do it!

Tags: SOA WCF Services

Josh Post By Josh Twist
1:58 AM
18 Nov 2009
Silverlight out-of-browser and initParams

Silverlight 3 supports a very cool 'deployment model' where you can run the Silverlight Application 'out-of-browser' (OOB) and kick it off from your start menu. It even works offline. This is the future, get to like it.

However, because the plug-in is no longer hosted in your page you lose all those juicy settings and, perhaps worst of all, you initialization parameters aren't available when the app runs OOB. This is frustrating because a lot of people pass in settings from their host web-application's web.config file using this very mechanism.

However, it only takes a little bit of code to work around this scenario by caching the initParams in isolated storage whenever the applicaiton is run in-browser. Here's some code that does just that:

private void Application_Startup(object sender, StartupEventArgs e)
{
    var mp = new MainPage();
    this.RootVisual = mp;

    IDictionary<string, string> initParams = LoadInitParams(e);

    // this just adds the init params to the MainPage for demo purposes only
    foreach (var kv in initParams)
    {
        mp.LayoutRoot.Children.Add(new TextBlock { Text = kv.Key, FontStyle = FontStyles.Italic });
        mp.LayoutRoot.Children.Add(new TextBlock { Text = kv.Value, Margin = new Thickness(5,0,0,0) });
    }
}

private static IDictionary<string, string> LoadInitParams(StartupEventArgs e)
{
    IDictionary<string, string> initParams;

    // if running out of browser retrieve 'initParams' from cache
    if (Application.Current.IsRunningOutOfBrowser)
    {
        using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("initParams.txt", System.IO.FileMode.Open, isf))
        {
            DataContractSerializer ser = new DataContractSerializer(typeof(Dictionary<string, string>));
            initParams = (Dictionary<string, string>)ser.ReadObject(stream);
        }
    }
    // otherwise write initParams to cache
    else
    {
        initParams = e.InitParams;

        using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("initParams.txt", System.IO.FileMode.Create, isf))
        {
            DataContractSerializer ser = new DataContractSerializer(typeof(Dictionary<string, string>));
            ser.WriteObject(stream, initParams);
        }
    }
    return initParams;
}

Easy peasy.

One recommendation here though is that you probably want a layer of indirection between Initalization Parameters and your 'silverlight configuration' in this case. The reason for this is the initParams will only get updated when you run the app in-browser. It's possible that your user will never run the app in-browser again. And even if the XAP gets updated your new parameters may never be seen, unless the app runs in-browser. So I'd recommend storing a static and constant URL in your initParameters that specifies an XML file (or web service) on the web server that contains your silverlight configuration.

You can then download this at will, even out-of-browser, whenever the network is available.

Tags: Silverlight

Josh Post By Josh Twist
1:26 PM
21 Oct 2009
Five minute recipe for a decent BoolToVisibilityConverter

There are a bunch of IValueConverters that WPF probably should ship with... MultiplyConverter, AdditionConverter etc. Rather oddly it does ship with one: The BooleanToVisibilityConverter:

However, I'm not a huge fan of the implementation as it gives me little control over what true and false actually map to. For example, should false be Collapsed or Visible? What if I want to invert? For these reasons I always craft my own (I really must start a codeplex project at some point to keep all these converters). Here it is:

public class BoolToVisibilityConverter : MarkupExtension, IValueConverter
{
    public BoolToVisibilityConverter()
    {
        TrueValue = Visibility.Visible;
        FalseValue = Visibility.Collapsed;
    }

    public Visibility TrueValue { get; set; }
    public Visibility FalseValue { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool val = System.Convert.ToBoolean(value);
        return val ? TrueValue : FalseValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return TrueValue.Equals(value) ? true : false;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

As discussed in a previous post, I've used my Converters as MarkupExtensions tip but I've also made the TrueValue and FalseValue completely configurable so there's a clear route for both inversion and choice between Collapsed and Hidden. In fact, you could even have True==Collapsed and False==Hidden if you liked - not sure what you'd use that for though. Note that we set sensible defaults in the constructor.

Here's how to use it:

<StackPanel VerticalAlignment="Bottom">
    <StackPanel.Resources>
        <local:BoolToVisibilityConverter FalseValue="Collapsed" x:Key="btvc" />
    </StackPanel.Resources>
    <CheckBox x:Name="HideOrShowCheck">Hide or show the text...</CheckBox>
    <TextBlock Text="Hello World!" Visibility="{Binding ElementName=HideOrShowCheck, Path=IsChecked,Converter={StaticResource btvc}}" />
</StackPanel>
        
Or, my preferred way:

<StackPanel VerticalAlignment="Bottom">
    <CheckBox x:Name="HideOrShowCheck">Hide or show the text...</CheckBox>
    <TextBlock Text="Hello World!" Visibility="{Binding ElementName=HideOrShowCheck, Path=IsChecked,Converter={local:BoolToVisibilityConverter FalseValue=Collapsed}}" />
</StackPanel>
        
Happy converting.

Josh Post By Josh Twist
9:26 AM
12 Oct 2009
MultiBinding for Silverlight 3

One of the key binding features missing from Silverlight 3 is MultiBinding and IMultiValueConverter support. In this post I'll walk through a custom implementation that uses a few tricks that you may want to leverage elsewhere.

First of all, I wanted to re-create the IMultiValueConverter from WPF in it's entirety. Here it is:

public interface IMultiValueConverter
{
    object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);
    object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);
}

That was easy. Now for the actual MultiBinding. In WPF a MultiBinding looks like this:

<TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
    <TextBlock.Text>
        <MultiBinding
            Converter="{StaticResource myNameConverter}"
            ConverterParameter="FormatLastFirst">
                <Binding Path="FirstName"/>
                <Binding Path="LastName"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Ideally I'd have liked to recreate this for Silverlight but without support for custom MarkupExtensions that's just not happening. Instead, we'll have to use another trick where we implement a non-visual FrameworkElement. We use a FrameworkElement because we want DependencyProperties that support Bindings and these have to belong to FrameworkElement in Silverlight (a DependencyObject isn't good enough in SL3 as it is in WPF). No matter.

The other trick is that we have to add this element to the Visual Tree. What? Yes, I know, it feels like a hack but really it isn't. Even the RIA team do it so it must be OK. The key thing is that our element is non-visual so it doesn't contribute to the Render pipeline (has 0x0 size etc...). This is what it might look like in use:

<binding:MultiBinding x:Name="mb" Converter="{StaticResource intsToBrushConverter}"
    NumberOfInputs="3"
    Input1="{Binding ElementName=red, Path=Value, Mode=TwoWay}"
    Input2="{Binding ElementName=green, Path=Value, Mode=TwoWay}"
    Input3="{Binding ElementName=blue, Path=Value, Mode=TwoWay}" />

<Border Background="{Binding ElementName=mb, Path=Output}" Margin="5"/>

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="1">
    <Slider x:Name="red" Minimum="0" Maximum="255" Margin="5" Orientation="Vertical"/>
    <Slider x:Name="green" Minimum="0" Maximum="255" Margin="5" Orientation="Vertical" />
    <Slider x:Name="blue" Minimum="0" Maximum="255" Margin="5" Orientation="Vertical" />
</StackPanel>

You might have guessed that I'm creating a Color Selector control. Wanna' see it in action? Go on then (can't see it? click here).

Here's the BrushConverter (IMultiConverter) that's used by the MultiBinding:

public class IntsToBrushConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        byte r = System.Convert.ToByte(values[0]);
        byte g = System.Convert.ToByte(values[1]);
        byte b = System.Convert.ToByte(values[2]);
        return new SolidColorBrush(Color.FromArgb(Byte.MaxValue, r, g, b));
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture
    {
        SolidColorBrush brush = (SolidColorBrush)value;
        return new object[] { brush.Color.R, brush.Color.G, brush.Color.B };
    }
}

Easy peasy. Want the code? Go on then:

  • Usual disclaimers apply - this is demoware and used very much at your own risk.
  • Download Source (12 KB)
  • Please leave some feedback in the comments if you like it.

Important Notes

You may have noticed a few strange features about our MultiBinding, e.g. how the inputs are specified on a number of Input1, Input2 and Input3 properties instead of on child controls. That's just the way it is I'm afraid (because Bindings only work on members of the visual tree, and since this is a non-visual element any child elements aren't part of the visual tree), and because of this you have to specify the NumberOfInputs you want - my version supports up to 5.

<binding:MultiBinding x:Name="mb" Converter="{StaticResource intsToBrushConverter}"
    NumberOfInputs="3"
    Input1="{Binding ElementName=red, Path=Value, Mode=TwoWay}"
    Input2="{Binding ElementName=green, Path=Value, Mode=TwoWay}"
    Input3="{Binding ElementName=blue, Path=Value, Mode=TwoWay}" />

You really can drop this control pretty much anywhere in your visual tree but it makes most sense to keep it close to the parts that need it. As always, your own mileage may vary. Any feedback appreciated in the comments.

Josh Post By Josh Twist
10:27 AM
23 Sep 2009
.NET Naming Conventions

I often get asked about the Naming Conventions I adhere to when writing code (C#, naturally).

It made sense to share these in a blog post so I can refer to it in future.

Some of these guidelines (well, one, the underscore on private fields) are negotiable as a matter of style. However, the public stuff is non-negotiable. For this is how .NET APIs should be and failure to adhere to this reflects badly on your code. No, no, no.

I thought a good way to present this would be an example class demonstrating the rules and some comments to help, so here goes:

using System;

// Namespaces are PascalCased
namespace TheJoyOfCode.NamingConventions
{
    // Class names are PascalCased
    public class ExampleClass
    {
        // All public fields, including constants are PascalCased
        public static const string PiAsAString = "3.14";

        // All private fields are camelCased with an underscore [1]
        private readonly string _privateMember;

        // All protected members are PascalCased
        protected int ProtectedField = 12;

        // All internal members are PascalCased
        internal int InternalField = 13;

        // All private methods are PascalCased
        // *** NOTE - All parameters are camelCased
        private double Multiply(double valueA, double valueB)
        {
            // local variables (scoped within a method) are camelCased (no underscore)
            double result = valueA * valueB;
            return result;
        }

        // All private Properties are PascalCased
        // *** NOTE - Acronyms of 2 characters are UPPERCASED (e.g. UI, IO)
        private string UIElementName { get; }

        // All (public and private) properties are PascalCased
        // *** NOTE - Acronyms longer than 2 characters are PascalCased (e.g. Html, Xml)
        public int HtmlLength { get; set; }

        // All public methods are PascalCased
        // *** NOTE - All parameters are camelCased
        // *** NOTE - Abbreviations are not treated as Acronyms (so _Id_entification is Id, not ID).
        private void AlignObjectById(string id, Alignment alignment)
        {
            throw new NotImplementedException();
        }

        // Nested classes are PascalCased, even Private ones
        private class NestedClass : IDisposable
        {
            public void Dispose()
            {
                throw new NotImplementedException();
            }
        }
    }

    // Enums are PascalCased and not plural (unless marked [Flags] in which case the name should be plural)
    public enum Alignment
    {
        // Enum members are PascalCased
        Top,
        Bottom,
        Left,
        Right,
    }
}

// [1] - Note the underscore isn't as recommended by StyleCop but since it applies only to private members, can be considered a matter of style and one that I personally use.

... and as for #region blocks I do not use regions and I don't negotiate with terrorists either.

Tags: C#

Josh Post By Josh Twist
9:26 AM
08 Sep 2009
A Suck Less Event Aggregator for Prism?

I heard on twitter the other day (Yes, I now tweet occasionally. If you'd like to waste literally seconds of your day you can follow me at joshtwist) that some folks at an Alt.Net UK event where giving P&P and Prism a rough ride. Specifically, they had some issues with the EventAggregator - citing Jeremy Miller's criticisms in this post Braindump on the Event Aggregator Pattern.

I need to say up front that I really like the EventAggregator in Prism - it's one of my favourite bits. However, I have to agree with some of the feedback. I've always found it odd that I have to go to the EventAggregator and ask for an 'event' object. Especially because the thing I get back isn't an event, but the 'bus' through which events travel.

CustomerSelectedEvent cse = eventAggregator.GetEvent<CustomerSelectedEvent>();
cse.Subscribe(c => CustomerHasBeenSelected(c));

// meanwhile, elsewhere...

CustomerSelectedEvent cse = eventAggregator.GetEvent<CustomerSelectedEvent>();
cse.Publish(customer);

However, once I've learned the API I've never found it obstructive. Nonetheless - I wondered, how hard would it be to create a wrapper that makes the Event Aggregator look something like you might expect it to look?

public interface ISuckLessEventAggregator
{
    void SendMessage<T>(T message);
    void Subscribe<T>(Action<T> action);
    void Subscribe<T>(Action<T> action, bool keepSubscriberReferenceAlive);
    void Subscribe<T>(Action<T> action, Microsoft.Practices.Composite.Presentation.Events.ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<T> where);
    void Unsubscribe<T>(Action<T> action);
}

The interface would look something like that I guess. And it would be used like so.

eventAggregator.Subscribe<Customer>(c => CustomerHasBeenSelected(c));

// meanwhile, elsewhere...

eventAggregator.Send(customer);

That certainly feels a bit better. However, there's no 'topic' described so this feels like a poor usage of the new interface as I can't distinguish Customer *selection* from other events involving the Customer type. Maybe this is better:

public class CustomerSelectedEvent
{
    public Customer Customer { get; set; }
}

// elsewhere

eventAggregator.Subscribe<CustomerSelectedEvent>(c => CustomerHasBeenSelected(c.Customer));

// meanwhile, elsewhere...

eventAggregator.Send(new CustomerSelectedEvent { Customer = customer} );

Now I prefer this over the existing pattern for a number of reasons

  1. It's just easier to read
  2. The 'event' class, CustomerSelectedEvent, is a POCO - no dependencies on the Prism pieces.
And how might this implementation look? Here's a first shot:

using System;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;

public class SuckLessEventAggregator : ISuckLessEventAggregator
{
    private readonly IEventAggregator _eventAggregator;

    public SuckLessEventAggregator(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    private CompositePresentationEvent<T> GetEventBus<T>()
    {
        var bus = _eventAggregator.GetEvent<CompositePresentationEvent<T>>();
        return bus;
    }
    
    public void SendMessage<T>(T message)
    {
        var bus = GetEventBus<T>();
        bus.Publish(message);
    }

    public void Subscribe<T>(Action<T> action)
    {
        var bus = GetEventBus<T>();
        bus.Subscribe(action);
    }

    public void Subscribe<T>(Action<T> action, bool keepSubscriberReferenceAlive)
    {
        var bus = GetEventBus<T>();
        bus.Subscribe(action, keepSubscriberReferenceAlive);
    }

    public void Subscribe<T>(Action<T> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<T> where)
    {
        var bus = GetEventBus<T>();
        bus.Subscribe(action, threadOption, keepSubscriberReferenceAlive, where);
    }
    
    public void Unusbscribe<T>(Action<T> action)
    {
        var bus = GetEventBus<T>();
        bus.Unsubscribe(action);
    }
    
    // You'd probably have more overloads but I'll wait for C# 4's Optional keyword :)
}

Does this feel better?

I realise that it doesn't address all of Jeremy's concerns (it's just the result of a short train journey's work so far). However, some of them I just don't agree with.

For example:

"2. The listeners should have little or preferably NO/ZILCH/NADA coupling to the event aggregator."

I'd much prefer an explicit dependency on the EventAggregator than a relatively implicit one to an IoC behavior. In either case, this is more of a religious argument than a technical one.

I also realise that most of this could have been implemented in Extension Methods but I think a separate, uncluttered API would be more intuitive.

Thoughts? Any holes in my quick implementation?

Josh Post By Josh Twist
1:27 AM
04 Aug 2009
How to work with PropertyChanged's smelly name string

Karl posted an interesting article recently INotifyPropertyChanged – How to remove the Property Name String Code Smell.

It'a nice implementation and the resulting code certainly looks a whole better. As Karl notes the biggest problem this approach faces is one with performance.

Notably, the proposed implementation is a lot slower when there are listeners wired up to the INotifyPropertyChanged plumbing.

The performance could be improved by caching the StackTrace based on an accompanying static key for each property, e.g.

private static readonly object _namePropertyKey = new object();

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        OnPropertyChanged(_namePropertyKey);
    }
}

However, this is probably just as prone to runtime errors in case somebody uses the wrong key with the wrong property.

With respect to the importance of performance then Karl is right to note that your users can only type so fast. But in some models and viewmodels, say containing a few hundred points that will be represented on a chart. That hit in performance could REALLY hurt.

My approach to this problem is to leave the smelly string where it is and automate the testing process using the Automatic Class Tester. This will automaticaly test that your properties are wired up appropriately and, if your class implements INotifyPropertyChanged it will also check that the appropriate PropertyChanged string name is fired.

Josh Post By Josh Twist
10:52 AM
02 Aug 2009
Silverlight, Validation and MVVM - Part II

The new Validation states for controls in Silverlight 3 sure look nice but there are a number of limitations. For starters, you can only invoke them through:

  • An exception thrown by a bound property setter
  • An exception thrown by a ValueConverter
The latter feels particularly unsavoury as you'll need to reuse the same converter wherever you want to bind to that property - a big violation of the DRY principle.

You can't even use the new ValidationAttributes from System.ComponentModel.DataAnnotations. Well, actually you can but you'd have to this inside the setter:

[Range(18, int.MaxValue, ErrorMessage="Must be 18 or over")]
public int Age
{
    get { return _age; }
    set
    {
        Validator.ValidateProperty(value, new ValidationContext(this, null, null)
        {
            MemberName = "Age",
        });
        _age = value;
        OnPropertyChanged("Age");
    }
}

(You can imagine an enhancement to this pattern using the SetValue concept I shared with my new snippets the other day).

What's particularly tricky is to display the invalid state if the value is never changed by the user. For example, you have a name field that is required:

[Reguired(ErrorMessage="Name is required")]
public string Name

This is bound to a TextBox:

<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" x:Name="NameTextBox" />
<Button Content="Save" x:Name="SaveButton" />

The problem is, the user might click save without ever entering the a name. Oh no!

Sure, we can catch that in our code (using the Validator type again, for example). However, there's no easy way of forcing the control to display the error. The only way to achieve this is to force the binding to update programmatically, like so:

BindingExpression binding = NameTextBox.GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();

Now, to get this working on any scale is going to require code-behind. Lots of code-behind. And everybody knows I hate this. The whole validation story at the moment isn't going to play at all well with Model-View-ViewModel (MVVM).

What we need is an easy way to Update all bindings from our ViewModel...

And so, I set about finding a more declarative way of achieving solving. My approach builds on my previous post Silverlight Validation and ViewModel.

Re-introducing the ValidationScope

In this update - the ValidationScope class becomes much more important and has more to offer than just an attached properties/behavior.

It now becomes an integral part of your ViewModel. Let's walk through a scenario. Here we'll have a ViewModel that exposes a Person property of type Person:

// properties snipped down for brevity
public class Person
{
    [Required(ErrorMessage= "Name is required")]
    public string Name {}

    [Required(ErrorMessage = "Salutation is required")]
    public string Salutation {}

    [Range(0, int.MaxValue, ErrorMessage = "Must be over 18")]
    public int Age {}
}

Nice and easy. Now the validation scope comes into play - we add an instance to our ViewModel because we'll access it via binding. To be honest, this could go almost anywhere you like provided it's accessible in a Binding (resources, in the Person class itself, anywhere you like!).

// properties snipped down for brevity
public class MainViewModel : INotifyPropertyChanged
{
    public ObservableCollection<string> Salutations {}
    public Person Person {}
    public ValidationScope PersonValidationScope {}
}

So there's our model and our ViewModel. Now for some view - our Xaml (again, simplified for brevity):

<StackPanel local:ValidationScope.ValidationScope="{Binding PersonValidationScope}">
        <TextBox
            Text="{Binding Person.Name, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}"
            local:ValidationScope.ValidateBoundProperty="Text" />
        <TextBox
            Text="{Binding Person.Age, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}"
            local:ValidationScope.ValidateBoundProperty="Text" />
        <ComboBox
            ItemsSource="{Binding Salutations}"     
         SelectedItem="{Binding Person.Salutation, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"
    local:ValidationScope.ValidateBoundProperty="SelectedItem" />
    <Button Content="Save" Click="SaveButtonClick" />
</StackPanel>

And the code-behind:

//Note - I'd normally use Prism's DelegateCommand and commanding support to avoid this code-behind but don't want to muddy the example
private void SaveButtonClick(object sender, RoutedEventArgs e)
{
_personViewModel.Save();
}

Finally, the Save method on the ViewModel

public void Save()
{
    // This causes all registered bindings to be updated
    PersonValidationScope.ValidateScope();
    if (PersonValidationScope.IsValid())
    {
        // Save changes!
    }
}

How it all works

Whilst getting here took me a whole morning of confusion - it's actually quite straightforward.

First, we use an attached behavior to pass the FrameworkElement we want to be the conceptual 'validation scope' within the VisualTree to our actual ValidationScope instance:

<StackPanel local:ValidationScope.ValidationScope="{Binding PersonValidationScope}">

Then we specify the property who is bound and might need a refresh for each control:

<TextBox local:ValidationScope.ValidateBoundProperty="Text" />
<ComboBox local:ValidationScope.ValidateBoundProperty="SelectedItem" />

Sadly, this is really a violation of the DRY principle anyway but it does have the added advantage of having to opt in your Bindings to the ValidationScope. Finally, when we're ready, we tell the ValidationScope to update all the bindings:

PersonValidationScope.ValidateScope();

This kicks the process into action with a crawl of the VisualTree inside the FrameworkElement registered as our scope (the StackPanel in this case) and hunts out any attached ValidateBoundProperty properties wired to controls. When it finds them it looks for the appropriate DependencyProperty (Text and SelectedItem in our demo)

demoware

If you're interested in this you'll want to see a working demo and the source code. Here's the former and the latter will follow in a minute. To bush the barrier, we actually have two validation scopes in the same view, side-by-side

Before you get to the source - bear in mind this is demoware/spike standard only and probably needs work. The usual disclaimers apply. Here are just some thing that haven't even been thought about in the current implementation:
  • binding to the same ValidationScope from two different FrameworkElements
  • performance could be improved, quite a bit of reflection
  • nested ValidationScopes
  • many more I'm sure
Finally, before you rush off make sure to double check that the new DataForm control and/or .NET RIA Services isn't really what you need to solve your validation requirements.

The source

Get it here and remember, this may damage your health and your house is at risk if you use it as it is: Download Source (15 KB)

UPDATE:Be sure to go on and read Part III in this series!

Josh Post By Josh Twist
7:51 AM
31 Jul 2009
New snippets for Silverlight and WPF

A while back I posted some snippets for WPF here: WPF Snippets for Visual Studio. I've been wanting to update these for a while now and finally got around to it this morning. Here are the new snippets.

basevm

This is a snippet that effectively replaces the inpc snippet (although that is still included for demos etc). The primary addition is that of a SetValue method that actually checks if values have been changed before raising the PropertyChanged event. Here's what the snippet looks like.

// TODO - consider making this class abstract if it is used as a base class
public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler pceh = PropertyChanged;
        if (pceh != null)
        {
            pceh(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    /// <summary>
    /// Set's the value of the target parameter (replacing the reference) if the value has changed. Also fires
    /// a PropertyChanged event if the value has changed.
    /// </summary>
    /// <typeparam name="T">The type of the property</typeparam>
    /// <param name="target">The target to be swapped out, if different to the value parameter</param>
    /// <param name="value">The new value</param>
    /// <param name="changedProperties">A list of properties whose value may have been impacted by this change and whose PropertyChanged event should be raised</param>
    /// <returns>True if the value is changed, False otherwise</returns>
    protected virtual bool SetValue<T>(ref T target, T value, params string[] changedProperties)
    {
        if (Object.Equals(target, value))
        {
            return false;
        }

        target = value;

        foreach (string property in changedProperties)
        {
            OnPropertyChanged(property);
        }

        return true;
    }
}

Note that it's also hinting that this would make a good base class for your ViewModel classes - but that's up to you.

propsv

This is the accompanying replacement for basevm - trumping propnp (although again, that is included for inpc users).

private int _age;

public int Age
{
    get { return _age; }
    set
    {
        SetValue(ref _age, value, "Age");
    }
}

SetValue takes a list of strings specifying what PropertyChanged events should fire. This is because you often want to fire Changes for dependant properties. E.g.

public bool IsLegalDrinkingAgeInUK
{
    get { return _age > 18; }
}

private int _age;

public int Age
{
    get { return _age; }
    set
    {
        SetValue(ref _age, value, "Age", "IsLegalDrinkingAgeInUK");
    }
}

SetValue also returns a bool in case you want to do some conditional processing based on whether the value was actually changed or not, e.g.:

public int Age
{
    get { return _age; }
    set
    {
        if (SetValue(ref _age, value, "Age", "IsLegalDrinkingAgeInUK"))
        {
            DoSomethingWhenAgeChanges();
        }
    }
}

depprop

Finally, I've really been wanting to add this to my snippets. Basically some enhancements to the built-in propdp with these new features:
  • Adds a Change handler for the dependency property
  • This one favours Silverlight by going for PropertyMetadata, instead of UIPropertyMetadata (WPF users just put the 'UI' back in)
  • Sets the default value of the dependency property using the default(type) syntax - should avoid nasty errors when you leave '0' instead of '0d' for a double,e tc.
Here's how it looks:

public double Minimum
{
    get { return (double)GetValue(MinimumProperty); }
    set { SetValue(MinimumProperty, value); }
}

public static readonly DependencyProperty MinimumProperty =
    DependencyProperty.Register("Minimum", typeof(double), typeof(MyDependencyObject), new PropertyMetadata(default(double), MinimumChanged));

private static void MinimumChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
{
    MyDependencyObject instance = (MyDependencyObject)source;
    // TODO - implement change handling here
}

Download

Enjoy: Download Snippets.zip (5KB).

For installation instructions see here: WPF Snippets for Visual Studio.

If you have any other suggestions for snippets you'd like to see, please leave a comment.

Josh Post By Josh Twist
1:44 AM
30 Jul 2009
Bindorama - Binding Craziness now for Silverlight too!

A while back I posted And now for something completely crazy: Binding without WPF where I proposed a class that would allow you to use WPF's awesome binding deep inside your own code away from any visuals - awesome stuff for some complex ViewModel scenarios.

I unimaginatively entitled the class BindingObject but here's the Silverlight version and I've decided to name him: Bindorama!

Here's the code:

public class Bindorama : FrameworkElement, IDisposable
{
    private bool _suppress;
    private Action<DependencyPropertyChangedEventArgs> _onChanged;

    public Bindorama(object source, string bindingPath, Action<DependencyPropertyChangedEventArgs> onChanged)
    {
        using (SuppressNotifications())
        {
            _onChanged = onChanged;

            Binding binding = new Binding(bindingPath);
            binding.Source = source;
            BindingOperations.SetBinding(this, ValueProperty, binding);
        }
    }

    public object Value
    {
        get { return (object)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register("Value", typeof(object), typeof(Bindorama), new PropertyMetadata(null, ValueChangedCallback));

    private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var instance = (Bindorama)d;
        Action<DependencyPropertyChangedEventArgs> onChanged = instance._onChanged;
        if (onChanged != null && !instance._suppress)
        {
            onChanged(e);
        }
    }

    public void Dispose()
    {
        BindingOperations.SetBinding(this, ValueProperty, null);
        _onChanged = null;
    }

    public IDisposable SuppressNotifications()
    {
        return new Supresser(this);
    }

    private class Supresser : IDisposable
    {
            private Bindorama _bindingObject;

        public Supresser(Bindorama bindingObject)
        {
            _bindingObject = bindingObject;
            _bindingObject._suppress = true;
        }

        public void Dispose()
        {
            _bindingObject._suppress = false;
        }
    }
}

What are the advantages of this over just subscribing to INotifyPropertyChanged?

  • Weak reference based - no more leaking memory.
  • Can go deep on properties: "Property.That.I.Want.To.Monitor" - this is hard to do well manually
  • Can use indexers: "Collection[0]"
And here's how you use him:

Bindorama b = new Bindorama(objectYouWantToMonitor, "Property.You.Want.To.Monitor", DelegateToFireOnChange);

public void DelegateToFireOnChange(DependencyPropertyChangedEventArgs args)
{
    MessageBox.Show(string.Format("NewValue: {0}, OldValue: {1}",
        args.NewValue,
        args.OldValue);
}

Awesome!

Note, if the instance of Bindorama gets garbage collected then the event will stop firing (obviously). So you may need to keep a reference to it to keep it alive. Of course, this has huge advantages to help prevent memory leaks that so often occur when we start registering for events.

If you need to deterministically stop the events firing, then dispose the Bindorama (b.Dispose()). It's IDisposable so you can use it inside a using block if necessary.

Finally, I thought some extension methods might make this easier to use:

public static class BindoramaExtensions
{
    public static IDisposable Watch(this INotifyPropertyChanged source, string propertyExpression, Action<DependencyPropertyChangedEventArgs> onChanged)
    {
        return CoreWatch(source, propertyExpression, onChanged);
    }

    public static IDisposable Watch(this DependencyObject source, string propertyExpression, Action<DependencyPropertyChangedEventArgs> onChanged)
    {
        return CoreWatch(source, propertyExpression, onChanged);
    }

    private static IDisposable CoreWatch(object source, string propertyExpression, Action<DependencyPropertyChangedEventArgs> onChanged)
    {
        return new Bindorama(source, propertyExpression, onChanged);
    }
}

Which means you can now simply 'Watch' any INotifyPropertyChanged instance of DependencyObject easy peasy:

objectYouWantToMonitor.Watch("Property.You.Want.To.Monitor", args => MessageBox.Show(args.NewValue.ToString()));

Note that this returns IDisposable and he'll need to remain rooted if you want to receive change notifications (or dispose him to stop listening).

Josh Post By Josh Twist
12:21 AM
28 Jul 2009
Creating a Range Slider in Silverlight (and some of the binding gotchas in SL3)

Yesterday, I posted about how to Create a Range Slider in WPF using composition within a UserControl.

Today, I want to do the same in Silverlight and _try_ to use the same technique(s).

The obvious things that need to change are:

  1. The Slider ControlTemplate
  2. Removing the ElementName binding
I can hear you all now: "No! Josh! Silverlight 3 has ElementName binding support! You don't need to remove it! Nooooo!".

Sadly though, we can't use it the way I did in yesterday's post. Let's recap the big tip I was using:

<UserControl x:Class="UserControlFun.RangeSlider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="root">
    <Slider x:Name="LowerSlider"
        Minimum="{Binding ElementName=root, Path=Minimum}"
        Maximum="{Binding ElementName=root, Path=Maximum}"
        Value="{Binding ElementName=root, Path=LowerValue}" />
    <Slider x:Name="UpperSlider"
        Minimum="{Binding ElementName=root, Path=Minimum}"
        Maximum="{Binding ElementName=root, Path=Maximum}"
        Value="{Binding ElementName=root, Path=UpperValue}" />
</UserControl>

As you can see we give the UserControl element a name. This is supported in WPF but not recommended in Silverlight. This is because in Silverlight an element can only have one name and therefore if we specify a Name where we use the control, like this:

<local:RangeSlider x:Name="overridingName" />

the internal ElementName binding will now fail (silently) because we changed the name. One solution might be to *not* rename the element where it's used but there's another problem: we can only use this control once or we'll have two elements with the same name.

This is very sad and I hope this is fixed in future releases. However, there is a workaround that seems to achieve what I want to achieve.

The trick is to use ambient binding (no ElementName) by programmatically setting the DataContext in the control's constructor:

public RangeSlider()
{
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(RangeSlider_Loaded);
    LayoutRoot.DataContext = this;
}

Notice that we specifically don't set this.DataContext = this;. That would break any bindings specified on the UserControl externally. Instead, we head for the first child of our UserControl - in this case, called 'LayoutRoot'.

Here's the Xaml for the UserControl:

<UserControl x:Class="UserControlFunSL3.RangeSlider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Grid x:Name="LayoutRoot" VerticalAlignment="Top">

    <!-- resources will go here -->

        <Border BorderThickness="0,1,0,0" BorderBrush="Black" VerticalAlignment="Center" Height="1" Margin="5,0,5,0"/>

        <Slider x:Name="LowerSlider"
            Minimum="{Binding Minimum}"
            Maximum="{Binding Maximum}"
            Value="{Binding LowerValue, Mode=TwoWay}"
            Margin="0,0,10,0"
            Template="{StaticResource sliderTemplate}"
            />

        <Slider x:Name="UpperSlider"
            Minimum="{Binding Minimum}"
            Maximum="{Binding Maximum}"
            Value="{Binding UpperValue, Mode=TwoWay}"
            Margin="10,0,0,0"
            Template="{StaticResource sliderTemplate}"
            />
    </Grid>
</UserControl>

Finally, we need our Silverlight specific Slider Template:

<Grid.Resources>
    <ControlTemplate x:Key="buttonTemplate" TargetType="RepeatButton">
    <!-- just empty-->
        <Grid />
    </ControlTemplate>
    <ControlTemplate x:Key="sliderTemplate" TargetType="Slider">
        <Grid x:Name="HorizontalTemplate" Background="{TemplateBinding Background}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <RepeatButton Template="{StaticResource buttonTemplate}" IsTabStop="False" IsEnabled="False" x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" Grid.Column="0"/>
            <Thumb IsTabStop="True" Height="18" x:Name="HorizontalThumb" Width="11" Grid.Column="1">
                <Thumb.Template>
                    <ControlTemplate TargetType="Thumb">
                        <Rectangle Fill="Red"
                            Stroke="Black"
                            StrokeThickness="1" />
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
            <RepeatButton Template="{StaticResource buttonTemplate}" IsTabStop="False" IsEnabled="False" x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" Grid.Column="2"/>
        </Grid>
    </ControlTemplate>

</Grid.Resources>

And we're done. Almost everything else is the same as our WPF control. Why not have a play with the control right here:

Or, get the source here: Download Source (7KB). Usual disclaimers for demoware apply.

Josh Post By Josh Twist
4:12 AM
16 Jul 2009