Fun binding an enum value to Viewbox child content

Catchy title eh? I've just solved this problem and thought I'd write about it. To be honest, I'm not sure it's the correct way, but it works, and at the moment, that's what matters.

The problem I had was this: I have a property on a class called 'TheEnum', which is defined as such:

private MyEnum theEnum;
public MyEnum TheEnum {
    get { return theEnum; }
    set {
      theEnum = value;
      RaisePropertyChanged("TheEnum");
    }
}

with 'RaisePropertyChanged' looking like this:

private void RaisePropertyChanged(string name){
  if(PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(name));
}

and MyEnum defined:

public enum MyEnum { OK, Warning, Error }

and what I wanted to do was have a Viewbox display a Path dependent on which value was set in the Enum.
Sooooo....

I have several resources such as:
<Path x:Shared="false" x:Key="GreenTick" Fill="#FF00FF00" Stroke="#FF000000" StrokeThickness="2" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeDashCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="4" StrokeDashOffset="0" Data="M7.69,404.61C7.69,404.61,122.85,534.30,145.89,587.28L244.93,587.28C286.39,460.60,447.62,158.16,585.82,52.21C614.45,15.39,542.52,0.20,484.47,24.57C396.99,61.30,231.98,341.74,201.17,409.22C157.40,420.74,111.34,335.51,111.34,335.51L7.69,404.61z"/>

Which (if you put into your xaml) will give you a nice green tick. First steps are to make sure that this works, so I define a Viewbox like so:

<Viewbox Stretch="Uniform" Child="{StaticResource GreenTick}"/>

Hit trusty F5 and have a shufty... Yup looks ok. Good.
So, now we want to convert an enum value to the resource, so lets get ourselves a Converter....

public class MyEnumConverter : IValueConverter
{
    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        switch ((MyEnum) value)
        {
            case MyEnum.OK:
                return Application.Current.FindResource("GreenTick");
            case MyEnum.Warning:
                return Application.Current.FindResource("YellowQuestionMark");
            case MyEnum.Error:
                return Application.Current.FindResource("RedCross");
            default:
                throw new ArgumentOutOfRangeException( "value" );
        }
    }
 
    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        throw new System.NotImplementedException();
    }
}

We switch on the value of the enum, and depending on what we have, we return one of three 'Resources'. Of course, now we need to setup the binding, which is 2 steps:

1. Define the Resource in the Window:
<Window xmlns:Converters="clr-namespace:Chris.Tests.Converters" &lt;!--More Stuff Here!--> >
<Window.Resources>
    <Converters:MyEnumConverter x:key="myEnumConverter"/>
</Window.Resources>

2. Then use this in the binding for the Viewbox Child...
<Viewbox Stretch="Uniform" Child="{Binding TheEnum, Converter={StaticResource myEnumConverter}}"/>

F5 aaaaaand.....

ARGH! XamlParseException --> A 'Binding' cannot be set on the 'Child' property of type 'Viewbox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

errr ok, but what now? Things were going so well... OK... What about something like an Image to hold it instead?

<Image Source="{StaticResource GreenTick}"/>
Nope. Image can't deal with Path. Hmmm...

Ahhh, what about making the actual resource a Viewbox?

<Viewbox x:Shared="false" x:Key="GreenTick" Stretch="Uniform"><Path Fill="#FF00FF00" Stroke="#FF000000" StrokeThickness="2" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeDashCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="4" StrokeDashOffset="0" Data="DATA HERE"/></Viewbox>

Obviously, this presents a problem in the sense that I don't really want to have a Viewbox inside of a Viewbox... So, lets change the container:

<ContentPresenter Child="{StaticResource GreenTick}"/>

F5, and Yup! We have a winner... Now let's just try a binding...

<ContentPresenter Child="{Binding TheEnum, Converter={StaticResource theEnumConverter}}"/>

Fingers crossed, F5 and....

Huzzah!!

So - quick recap - Need Converter, define the resource *as* a Viewbox, show in a ContentPresenter.

Print | posted @ Monday, January 19, 2009 3:14 PM

Comments on this entry:

No comments posted yet.

Post A Comment
Title:
Name:
Email:
Comment:
Verification: