When I wish to bind a control to a property of my object, I have to provide the name of the property as a string. This is not very good because:
- If the property is removed or renamed, I don’t get a compiler warning.
- If a rename the property with a refactoring tool, it is likely the data binding will not be updated.
- I don’t get an error until runtime if the type of the property is wrong, e.g. binding an integer to a date chooser.
Is there a design-pattern that gets round this, but still has the ease of use of data-binding?
(This is a problem in WinForm, Asp.net and WPF and most likely lots of other systems)
I have now found "workarounds for nameof() operator in C#: typesafe databinding" that also has a good starting point for a solution.
If you are willing to use a post processor after compiling your code, notifypropertyweaver is well worth looking at.
Anyone knows of a good solution for WPF when the bindings are done in XML rather then C#?
The Framework 4.5 provides us with the
CallerMemberNameAttribute
, which makes passing the property name as a string unnecessary:If you're working on Framework 4.0 with KB2468871 installed, you can install the Microsoft BCL Compatibility Pack via nuget, which also provides this attribute.
x:bind (also called "compiled data bindings") for XAML (universal app) in windows 10 and windows phone 10 may solve this problem, see https://channel9.msdn.com/Events/Build/2015/3-635
I can't find the on line docs for it, but have not put much effort in, as it is something I will not be using for some time. However this answer should be a useful pointer to other people.
One way to get feedback if your bindings are broken, is to create a DataTemplate and declare its DataType to be the type of the ViewModel that it binds to e.g. if you have a PersonView and a PersonViewModel you would do the following:
Declare a DataTemplate with DataType = PersonViewModel and a key (e.g. PersonTemplate)
Cut all PersonView xaml and paste it into the data template (which ideally can just be at the top of the PersonView.
3a. Create a ContentControl and set the ContentTemplate = PersonTemplate and bind its Content to the PersonViewModel.
3b. Another option is to not give a key to the DataTemplate and not set the ContentTemplate of the ContentControl. In this case WPF will figure out what DataTemplate to use, since it knows what type of object you are binding to. It will search up the tree and find your DataTemplate and since it matches the type of the binding, it will automatically apply it as the ContentTemplate.
You end up with essentially the same view as before, but since you mapped the DataTemplate to an underlying DataType, tools like Resharper can give you feedback (via Color identifiers - Resharper-Options-Settings-Color Identifiers) as to wether your bindings are broken or not.
You still won't get compiler warnings, but can visually check for broken bindings, which is better than having to check back and forth between your view and viewmodel.
Another advantage of this additional information you give, is, that it can also be used in renaming refactorings. As far as I remember Resharper is able to automatically rename bindings on typed DataTemplates when the underlying ViewModel's property name is changed and vice versa.
This blog article raises some good questions about the performance of this approach. You could improve upon those shortcomings by converting the expression to a string as part of some kind of static initialization.
The actual mechanics might be a little unsightly, but it would still be type-safe, and approximately equal performance to the raw INotifyPropertyChanged.
Something kind of like this:
Yes, Ian, that are exactly the problems with name-string driven data binding. You asked for a design-pattern. I designed the Type-Safe View Model (TVM) pattern that is a concretion of the View Model part of the Model-View-ViewModel (MVVM) pattern. It is based on a type-safe binding, similar to your own answer. I've just posted a solution for WPF:
http://www.codeproject.com/Articles/450688/Enhanced-MVVM-Design-w-Type-Safe-View-Models-TVM
Thanks to Oliver for getting me started I now have a solution that both supports refactoring and is type safe. It also let me implement INotifyPropertyChanged so it copes with properties being renamed.
It’s usage looks like:
The person class shows how to implemented INotifyPropertyChanged in a type safe way (or see this answer for a other rather nice way of implementing INotifyPropertyChanged, ActiveSharp - Automatic INotifyPropertyChanged also looks good ):
The WinForms binding helper class has the meat in it that makes it all work:
This makes use of a lot of the new stuff in C# 3.5 and shows just what is possible. Now if only we had hygienic macros lisp programmer may stop calling us second class citizens)