Strongly typed databinding in WinForms – aka. no more magic strings!
Posted on July 24, 2013
I’ve been working on a WinForms project for a while and I’m getting progressively more tired of the magic strings used when doing databinding. (See MSDN documentation here) The problem is that the datamember of the datasource being bound to the control is a plain old System.String:
e.g:
lblName.DataBindings.Add("Text", myViewEntity, "UserName");
I can live with the propertyName (“Text”) being a System.String, as this property will probably not change the name in the next many releases of .net, but the “DataMember” is nagging me.
The problem is:
* Misspelling is only discovered at run time
* Renaming the property will cause the databinding to break – at runtime.
The last point is mostly handled by using productivity tools such as ReSharper, but I have often had the experience that the ReSharper refactoring didn’t rename correctly – probably because I was blindly pressing yes or no when asked to refactor.
A few weeks ago, I started to look around for a better solution and came up with this little snippet:
public static string GetPropertyName(Expression expression) { var body = (MemberExpression)expression.Body; return body.Member.Name; }
This little snippet could be used like this:
lblName.DataBindings.Add("Text", myViewEntity, GetPropertyName(() => myViewEntity.UserName));
- And the magic string has disappeared :-)
After a little more work, I ended up making an extension method for the BindingCollection class:
public static Binding Add(this ControlBindingsCollection collection, string propertyname, object dataSolurce, Expression expression, bool formattingEnabled = true, DataSourceUpdateMode updateMode = DataSourceUpdateMode.OnPropertyChanged, object nullValue = null, string formatString = "", IFormatProvider formatProvider = null) { return collection.Add(propertyname, dataSolurce, GetPropertyName(expression), formattingEnabled, updateMode, nullValue, formatString, formatProvider); }
Using this method, I could write the following code when binding:
lblName.DataBindings.Add("Text", myViewEntity, () => myViewEntity.UserName);
Now we're talking!
Finally I wrote a whole extension library containing the most common bindings - for binding to a Text, Enabled, Checked etc. causing my code to look like this:
lblName.BindToText(myViewEntity, () => myViewEntity.UserName);
Check out the library in the attached .cs file.