In my WPF app, I use a WCF service to fetch data.
So naturally, at some point i had “complex” objects that require a DataContract to be passed as a whole to the WPF app.
Now of course, I need to respond to changes, and I implement INotifyPropertyChanged on my ViewModels, however since some objects are actually DataContracts, I would have to recompose those so that they implement INotifyPropertyChanged.
I feel like it’s messy.
What i tried to do is implement the interface directly on the DataContract definition, but I can’t react properly to a change.
For example, if a Two-Way databound TextBox has its text changed, my ViewModel should react to it by changing the value in the corresponding SQL table (through the WCF service), but since the object is defined on WCF side, I can’t do that in the setter of the property.
What I do for now, is subscribe to the PropertyChanged event of the DataContracts, and use reflection to know which property changed and its new value.
But those objects are held in an ObservableCollection<T>, that’s a lot of events, and it feels very brittle… what if i add/remove an element from the collection for example?
I do it like this (this is bad I think):
foreach (ImageInfo imgi in (param.Images as ObservableCollection<ImageInfo>))
{
imgi.PropertyChanged += (sender, args) =>
{
object newValue = Tools.GetProperty((sender as ImageInfo), args.PropertyName);
};
}
And then I’d send it back to the WCF service.
Is there a more elegant solution to this? should I implement INotifyPropertyChanged on the ViewModel only, and recompose the DataContracts instead?
Thanks!
Alright so after some time thinking it through, I implemented it like this for now but it might change because I meet with an expert next monday (I’ll update if he gives me a better idea).
1) The WCF service has a DataContract such as:
Note: INotifyPropertyChanged is implemented the usual way, i just left it out for readability, and because i dont have my snippets on this computer.
When GetMyData() is called on the service, it returns an instance of that class, with only “MyField” populated. MyFieldModified is left to null.
On my DAL (so client-side), where MyWcfData is recieved:
The point here is that the data needs to be duplicated so that i can keep track of changes, and only update a property once in the end, even if the user changed it 10 times (i just compare everytime to the original value). But I don’t want to send duplicated data over the wire, so instead i do the duplication in the DAL, before any business object has access to it.
On the ViewModel of my view:
And then last but not least, in my XAML, i bind to
MyFieldModified(in Two-Way binding) in aTextBox.I then use
System.Windows.Interactivityto call aDelegateCommandupon theTextChangedevent.When that last command is fired, i put the change in a Queue (to keep track of the changes order) and i send it back to the Wcf service for data persistency when the user presses a Save button.
Note: I actually use a custom-made
ObservableQueue<T>so that i can keep track of the number of changes and enable the save button accordingly through binding. I will make a blog post about it so stay tuned 😉Note2: I gave up on making it save every tiny change made instantly, even though in this case it would have worked because it’s not a feature much used, and few changes are expected; but as pointed out in other answers it’s bad practice.