Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / WPF

WPF Dynamic View Model with Enum Support

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
2 Aug 2012CPOL4 min read 29.1K   346   17   6
A technique to create a Dynamic View Model that handles enums.

Introduction

If you’ve used WPF then you’ve used binding to connect the values in your business objects/models with the properties of WPF controls. You’d typically assign the DataContext of the window to a view model which will manipulate the properties of the model. In a lot of scenarios the view model will repeat the properties of the model that you want to expose to the UI. Being kind of lazy efficient, the idea of writing all this glue code and maintaining it doesn’t appeal to me. Luckily it’s possible to create a dynamic view model in c# that can be used as a general wrapper for other classes.

The dynamic view model works well for basic types like strings and numbers but not so well for enums. The purpose of this article is to explain one way of dealing with enums that doesn’t require much effort. Once the generic view model is defined all that’s required to make it work is to add description attributes to the enum and do some easy binding in the XAML code. 

Background 

The original article that I base this idea on is found at: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx. Also I needed a way of converting the enum to a string and vice versa, read about that here: http://blog.spontaneouspublicity.com/associating-strings-with-enums-in-c.

Typically you would provide the user with a list of options to select the value of an enum field. That could be a list box, combo box or a set of radio buttons. The example I will be using is a real estate sales application and I’ll be using a list box. The RealProperty class has properties such as an address, sale price, asking price, and a property type (e.g. detached house, semi-detached house, etc.) which is an enum of type EPropertyType. We’ll bind the selected value of a list box or combo box to the value of the PropertyType property and bind the SourceItems property to a list of possible values.

The properties used in the XAML code won’t be defined in DynamicViewModel so what happens when the properties aren’t found is that either TryGetMember or TrySetMember is called. We can determine if the property is an enum in the TryGet/SetMember functions and either return the description of the value or convert a description to a value. Another thing we can do is have our view model object handle requests for a property that will return all the descriptions for the values an enum property can have. In the example code the list box’s SelectedItem property is bound to “PropertyType” and the ItemsSource property is bound to “PropertyType_All” which is a special name that DynamicViewModel recognizes. The “_All” property will return a list of descriptions for all the possible values it can be assigned to using reflection. 

Using the code  

The first step is to have descriptions of the options in your enum. Simply add some Description attributes as shown in the code below.

C#
public enum EPropertyType
{
    [Description("Detached")]
    Detached,
    [Description("Semi-detached")]
    SemiDetached,
    [Description("Townhouse")]
    Townhouse,
    [Description("Highrise Condominium")]
    HighriseCondo,
    [Description("Townhouse Condominium")]
    CondoTownhouse
}

Next we need to initialize the DataContext with a DynamicViewModel object: 

C#
_model = new RealProperty()
{
    Address = "1 Yonge Street",
    AskingPrice = 900000.0,
    SellingPrice = 869000.0,
    PropertyType = EPropertyType.HighriseCondo
};
DataContext = new DynamicViewModel(_model);

Inside the XAML code, we can now refer to properties within the Model. For basic controls all we do is refer to the property name and we're done. 

XML
<textbox text="{Binding Path=Address}" grid.column="1" name="textBox1" margin="0,9,12,3" height="23" />

For list boxes that use enums all we need to do is bind the property to SelectedItem and the property name with “_All” appended to it for the SourceItems property. 

XML
<listbox grid.column="1" name="listBox1" margin="0,12,12,8" 
  itemssource="{Binding Path=PropertyType_All}" selectedvalue="{Binding Path=PropertyType}" grid.row="1" />

The result is that the control will be populated with the descriptions from the enum and DynamicViewModel will handle all the conversions for us.   

Points of Interest  

Because we’re using reflection a lot this method will be significantly slower than using model specific view models. However in a typical application the impact will be too small to notice. The other consequence is that using the binding dialog to bind to a path in Visual Studio will not work since we’re not using a class with specific properties. What this means is that all binding will need to be done in the XAML manually. For me it hasn’t been a big deal because I find the interface more difficult to use anyways. You might want to try using the model itself for the design time datacontext which will allow the binding dialog to work and not affect the app at run time, see http://karlshifflett.wordpress.com/2009/10/28/ddesigninstance-ddesigndata-in-visual-studio-2010-beta2/

The solution as presented does not yet deal with localization. For that you’ll need to modify the code in DynamicViewModel to look for the descriptions in a resource file. One way to do it would be to have a standard format for the names in the resource like Desc_EPropertyType_Detached and then we look that up using the type/name of the value in the enum inside TryGetMember/TrySetMember

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Excel Adviser
Canada Canada
I am a freelance software developer with a variety of different interests. My main area of expertise is Microsoft Office add-ins (Excel/Outlook mostly) but I also develop Windows applications, Access Databases and Excel macros . I develop in VBA, C# and C++. My website exceladviser.com has articles on Excel, Access, Microsoft Office development, and general Windows programming (WPF, etc.).

Comments and Discussions

 
Questionnike Pin
CFYTYU7-Aug-12 17:42
CFYTYU7-Aug-12 17:42 
QuestionAmazing!! Pin
Omar Gameel Salem2-Aug-12 12:27
professionalOmar Gameel Salem2-Aug-12 12:27 
AnswerRe: Amazing!! Pin
Steve L. Powell2-Aug-12 18:10
Steve L. Powell2-Aug-12 18:10 
GeneralMy vote of 5 Pin
Christian Amado2-Aug-12 10:37
professionalChristian Amado2-Aug-12 10:37 
SuggestionJust what I was looking for Pin
Nick Isely1-Aug-12 15:42
Nick Isely1-Aug-12 15:42 
Great article. I was trying to find a way to do something very similar to this and this helps me out a lot. One thing though in the DynamicViewModel class you should check that the PropertyChanged event is not null before calling it. Otherwise if you assign a property before setting the dataContext on your view this will throw an exception.

C#
protected void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            } 
        }


Cheers
GeneralRe: Just what I was looking for Pin
Steve L. Powell2-Aug-12 9:11
Steve L. Powell2-Aug-12 9:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.