Software. Efficiency. Scalability.

Entia non sunt multiplicanda praeter necessitatem

Posts Tagged ‘mvvm

Why people don’t switch from WinForms to WPF

with one comment

I posted this as a comment here:

http://10rem.net/blog/2010/11/16/windows-forms-developers-tell-me-about-your-applications

and figured I’ll re-post it in my blog.

I have a lot of experience designing WinForms apps. Here is a screenshot from my the latest app I designed: http://execqview.com/images/facility-age-gender.gif.

This is a very simple screen. There are quite a few of more complex screens with hundreds of controls and a lot of data binding/data entry.

I had an opportunity to move to WPF, however I ran into some problems that prevented me from doing so:

1) Lack of business controls. WinForms doesn’t have a lot of good controls built in, but there are mature 3rd party libraries like DevExpress. For instance, take one of the most common controls in business apps: data grid. The grid from my screenshot up above comes with bands, multi sorting, totals, column selection, grouping, reordering, filtering, incremental search, custom cell rendering, cell controls, export to excel, and many other features. It can hold 100,000 records without any consequences to performance whatsoever. This is just one example. Tree view, tree list, scheduling controls, layouts, menu controls, ribbon controls, tab controls, charts, etc. All these things are readily available for WinForms development and provide an amazing productivity boost. The market for WPF controls is a lot weaker. Even established vendors like DevExpress have rather weak libraries for WPF.

2) Incredibly complicated design system. In WinForms you have controls that you can anchor to other controls- a very simple concept. In WPF you have different layouts that are cumbersome and yet inferior to anchoring in terms of real work. On top of it, you have access to myriads of properties such as gradients, layouts, panes, paths, resources, templates, 3D, timelines, and many other things. It’s just crazy complicated and almost assumes that you have to have a designer on the team. Setting up even a simple application requires a lot more work with WPF which results in lower productivity.

3) As a developer, you can’t leverage almost anything from your WinForms experience. Literally, you have to throw what you know away, clear your mind, and embrace all kinds of new concepts such as MVVM, new data binding, new control structure and design, resources, etc. You have to learn new tools such as Blend. It takes a while to get productive using all these new concepts and tools. We are talking about a serious learning curve here, a curve that is not easily justified at the moment.

4) Most WPF applications don’t have a good feel to them. I am sorry, but it’s true. They are slow, clunky, and non-native looking. You CAN make them look slick and flashy, but it requires a lot of effort and a set of strong artistic skills. Unfortunately, most GUI applications are written by businesses for businesses. Teams don’t have access to designers and have very strict time lines. Not a lot of mainstream developers have a luxury of turning their apps into a piece of art.

Essentially, it takes a lot more effort and time to write WPF applications and unless you need a very flashy app there are no clear benefits that you gain. There is

Written by Mikhail Opletayev

November 18, 2010 at 6:58 pm

Posted in development

Tagged with , , , , ,

Flexible vs. structured data for visual binding

leave a comment »

Overview

If you have ever written a visual application, you know how painful it can be to bind all the textboxes, comboboxes, buttons, lists, trees, grids, action bars, etc. to your data model. I know some people may think that the problem has been successfully solved in .NET with System.Forms.BindingSource, strongly typed datasets, and other tools that Microsoft provides. I beg to differ. All these tools work great in small examples. However, if you try to scale them for a large application visualizing complex data structures, there is a lot to be wished for.

Data binding can be extremely tedious and time consuming. It also limits the changes you can do to your data model.

Direct binding

The devil, as usual, is in the details. Often times the optimal way to visualize the data differs significantly from the optimal way to store the data. It creates an impediment that needs to be overcome.

If you are working with structured data (classes or strongly typed data sets), you will have to accommodate for the difference on the data binding level. You will need to configure rules your visual components will use to extract and present the appropriate pieces of data from your data model.

Some rules can be relatively simple. Say, you want to display a date in a specific format. A visual control might let you configure the date format. If you display a numeric value in a grid, you might be able to configure the column to show numbers are currency.

Some rules can be more complicated. Imagine a class like this:

public class Occurrence {
  public string Code;
  public DateTime Begins;
  public DateTime Ends;
}

Now, here comes trouble. In .NET DateTime is a value type and cannot represent a null. A common practice is to set the value to DateTime.MinValue. Of course, we don’t want to see 1/1/0001 when we are displaying a list of Occurrence objects in a grid, so normally we’d have to go and update our Occurrence class to look something like this:

public class Occurrence {
public string Code;
public DateTime Begins;
public DateTime Ends;

  public string BeginsString {
    get {
      return Begins == DateTime.MinValue?
        string.Empty: Begins.ToString();
    }
  }
  public string EndsString {
    get {
      return Ends == DateTime.MinValue?
        string.Empty: Ends.ToString();
    }
  }
}

Now we can display BeginsString and EndsString in a grid, instead of Begins and Ends. It will properly show empty cells when displaying a record. Essentially, we introduced two properties to overcome the impedance I mentioned.

Control Pads

Consider the two bad things that happened in the example above:

  1. We had to go and change the model for the view. It is a generally bad practice and it’s not always possible to change the model like this.
  2. Our model now dictates the view how dates are supposed to be displayed via ToString() method. We really don’t want that. The view is supposed to dictate visual formats and such, not the model.

A solution to that can be found in introducing a 3rd party instead of modifying the model. I call classes like that control pads. It’s an entity that connects the model to the view, acting like a broker.

For our example above a control pad will direct how Occurrence records are displayed in a gird and will display empty values for the cells containing DateTime.MinValue.

This is by no means a new idea, it has been around for years. The limitations of this approach are well known. For complex model structures it either creates a lot of different control pads (more entities = bad) or it forces developers to generalize control pads and use configuration (things get hairy). At some point control pads require their own event routing, and things get even more complicated.

Model-View-ViewModel

Control pads are for controls, but imagine creating one big fat control pad for the whole page, screen, form, or whatever view you have. This will get you a ViewModel.

Microsoft calls this approach a MVVM (or Model-View-ViewModel Design Pattern).  It’s somewhat based on Martin “UML” Fowler’s Presentation Model (note that work-in-progress remark on top of the page in conjunction with May, 2004 publishing date). It is presented as a new and revolutionary approach, which, of course, it neither. It wasn’t called a pattern or MVVM but the idea has been around for years.

The idea is simple. The difference between the view and the model is accommodated by creating a ViewModel. The number of the view models is limited to the number of views in your application. It provides for any form of data transformation and flexibility and it’s very friendly for unit testing.

It’s a decent approach, I used it for some of my apps. The downsides of it are low re-usability of the ViewModel code and the number of extra entities you might need to create.

Flexible Data

Another way of dealing with the data can seem quite obvious but is actually not used as much in visual applications, outside of web apps. If binding to the original data model can get complicated and you don’t want to use MVVM, then you can use flexible data.

Flexible data is a fancy way to call map/list data- sort of what Google uses in its Closure Templates. Think of JavaScript arrays and objects, where an object is essentially a hash map of properties and arrays are just list of objects.

This is how it works:

  1. You get your structured data. You do want to keep your data structured for storage and processing out of performance considerations.
  2. When you need to visualize your data, you map it into a flexible map-list model that is tailored for your view.
  3. You display the data out of your flexible model. It’s easy because the model is compatible with the view.
  4. (Optional) you collect the changes and apply then back to your structured model, then save them.

Yes, it encourages creating a copy of the data. But, for a visual application, it’s totally worth it. Consider this code for the example above:

class MyView {
  public ListData GetOccurrenceList( Occurrence[] source ) {
    ListData list = new ListData();
    foreach( Occurrence o in source ) {
      MapData data = new MapData();
      data.Add( "Code", o.Code );
      if( o.Begins != DateTime.MinValue )
        data.Add( "Begins", o.Begins );
      if( o.Ends != DateTime.MinValue )
        data.Add( "Ends", o.Ends );
      data.Add( "Source", o );
      list.Add( data );
    }
  }
}

Now all you need is a single control pad for a grid that takes ListData and displays the maps inside it as records. If you don’t like the way the data is displayed, you can add formatting, combining, totals, averages, etc. to the resulting map. Note how I also assigned the original record to the “Source” key. You don’t have to do this, but, if you want to, it allows for the link to the original object. You can store changes in the same map and then apply them back to the original record, if you need it.

Conclusion

Flexible data allows you to avoid creating entities where they are not needed. It works great for web applications because essentially this is JSON (JavaScript Object Notation), the native way JavaScript stores data. This approach works for visual applications as well, be it WinForms or WPF. Give it a try, you’ll might just like the flexibility and simplicity of it.

Written by Mikhail Opletayev

March 10, 2010 at 8:18 pm

Posted in development

Tagged with , , , , , ,

Follow

Get every new post delivered to your Inbox.