views:

868

answers:

8

Ok, So I have been stalled in my latest non-work project, trying to use WPF. I am just frankly annoyed at databinding. I thought it was supposed to make things simpler by binding data directly to the UI. But the more I learn about having to implement INotifyPropertyChanged to get things to notify the UI if they changed, seems to make the whole thing counter productive.

Am I missing something? It seems like a bunch of work and having to make the classes implemented INotifyPropertyChanged seems like a fishy way to get databinding to work.

What am I missing? I must be missing something. Please enlighten me into how to make databinding easy, or at the least straightforward.

+4  A: 

If you want the UI be notified when the underlying data source changes, then you need some sort of notification mechanism. For WPF, INotifyPropertyChanged is that mechanism.

It's the same in Windows Forms as well, but Windows Forms also supports the old notification mechanism, where you have an event with the name <Property>Changed.

However, neither of these required these mechanisms if all you want to do is bind to the data once and display it.

If you are ok with not receiving notifications, then just bind to the data source and it will work.

casperOne
So any time a property of a class changes we have to have it raise the PropertyChanged event? That seems tedious. What if we don't even have the code for the class we want to bind to? Does this not get messy?
Alex Baranosky
GordonG, this is where the Model-View-ViewModel pattern is highly recommended. Your ViewModel (middle layer) essentially handles this by allowing you to re-expose the underlying Model properties, but your View databinds to the ViewModel's re-exposed properties (NOT the model's!).
KP Adrian
(continued from above) Your ViewModel implements INotifyPropertyChanged and for 'get' calls you just return the underlying model's value per-property, but on 'set' calls, you both set the underlying model's property value AND you fire PropertyChanged so the View sees the updated value.
KP Adrian
+4  A: 

Truth be told, I haven't seen that it was that bad, and think it a highly workable solution.

Take this simple, Data Model object:

Public Class SimpleItemViewModel
Implements INotifyPropertyChanged

Private _item As String 
Public Property Item As String
   Get 
       return _item 
   End Get 
   Set (value as string) 
      _item = value : OnPropertyChanged("Item") 
   End Set 
End Property 

Protected Overridable Sub OnPropertyChanged(propChange as string) 
   Raise Event PropertChanged(me, new PropertyChangedEventArgs(propChange))
End Sub 
Public Event PropertyChanged(sender as object, e as PropertyChangedEventArgs)
End Class

That is easily bound to a simple Textbox via:

<Textbox Text="{Binding Item}" />

additionally, if I wanted to have a DIRTY flag, I can easily put the flag being set in the OnPropertyChanged sub, and easily determine if I need to save any user changes or not.

I have found it easiest to have a set of classes which rest between the Data Access layer and the UI which holds this stuff. You can even have your Business Logic and DAL pass these classes around rather than the atomic values.

Stephen Wrighton
Just remember that the above Text="{Binding Item}" works because of the idea of an inherited data context. Your View's data context IS the ViewModel.
KP Adrian
The above syntax is verbose, but it allows you to fire PropertyChanged events at will. You could fire off several such events when you set one value (maybe the other properties that change only have getters because they are computed properties).
KP Adrian
KP - Exactly. Additionally, if you have subcontrols, or even containers, you can assign additional view models to those container's data context programmatically.
Stephen Wrighton
I was responding to the OP, but your latest comment is exactly what makes it so incredibly powerful. One simple this.DataContext = customViewModel line in the constructor/loaded handler of your root container (window, master user control), and enjoy the magic of inherited values. Isn't it great?
KP Adrian
A: 

DataBinding is the only way to implement a model-view pattern in WPF/Silverlight. Your models can be UI-stupid by implementing INotifyPropertyChanged, which isolates them from the UI. It also saves a lot of UI code when stuffing information into the UI.

Another benefit that I enjoy is the ability to further bind child controls with the same data by using the { Binding } shortcut.

BC
A: 

First, INotifyPropertyChanged isn't the only way to get data binding to work - dependency properties work too.

Second, INotifyPropertyChanged can be implemented with just one line of code in your entity class, if you use AOP - you don't actually have to do all those notification calls yourself.

Overall, I'd say data binding is a great boon, especially when you're doing code generation to make automatically bound controls from some data source.

Dmitri Nesteruk
+2  A: 

Implementing INotifyProperty changed is not particularly difficult, seeing as it only has one member.

If you don't expect changes in the underlying object then don't worry about INotifyProperty changed, and use a Binding with Mode=OneTime.

If the underlying object can change and you want the GUI to reflect those changes, then how else can this be achieved without the kind of notification that INotifyProperty changed provides? It's not reasonable to expect a bound item to poll its binding's source.

Personally I've found WPF has taken some time to get to grips with, but now that I'm gaining comfort I'm finding it incredibly powerful and enjoyable to work with. I encourage anyone who's finding WPF challenging to stick with it.

Drew Noakes
A: 

If you're looking for a good way to think about structuring your data binding, then aim to set a DataContext on your logical tree only once, then use binding paths to populate the various parts of your UI.

Drew Noakes
A: 

Be as declarative as you can in your binding. Let the template system do it's job and make heavy use of DataTemplates that specify explicit DataTypes.

Drew Noakes
+1  A: 

Binding in XAML is quite easy, however, dynamic WPF data binding in code is painful and confusing.

Damien
So it ISN'T me after all!
Alex Baranosky