In CSLA 3.8 I was maintaining a list of dirty properties by overriding the OnPropertyChanged event and adding the propertyname to an internal list of strings if it didn't already exist. Then I would clear that list in an override of MarkOld. This worked without any issue in 3.8.
But now in 4.3 the OnPropertyChanged event seems to be working differently with the new Rules system. In 3.8 I would change a property, and I would get a single OnPropertyChanged event thrown for that property. But in 4.2 it is also throwing the OnPropertyChanged for each dependent property of the property I changed. As a result, my dirty properties list contains a bunch of properties in it that aren't actually dirty because they were never changed.
Further, there are 2 OnPropertyChanged methods, one with a string parameter and one with a propertyinfo parameter. I've tried both of them and while the string parameter method would be thrown for the changed property and all it's dependent properties, the propertyinfo parameter method wasn't being thrown at all.
So my question is, what should I now be doing to keep track of a dirty properties list in 4.3? Should I be using another method altogether?
Here is my code in my base class right now that is being thrown for the changed property and its dependencies:
Public Shared ReadOnly DirtyPropertiesProperty As PropertyInfo(Of Collection(Of String)) = RegisterProperty(Of Collection(Of String))(Function(obj As MyBusinessBase(Of T)) obj.DirtyProperties, "Dirty Properties", New Collection(Of String)) ''' <summary> ''' A collection of the properties that have been changed ''' </summary> Public Property DirtyProperties() As Collection(Of String) Get Return GetProperty(DirtyPropertiesProperty) End Get Set(ByVal value As Collection(Of String)) SetProperty(DirtyPropertiesProperty, value) End Set End Property
Protected Overrides Sub OnPropertyChanged(ByVal propertyName As String) MyBase.OnPropertyChanged(propertyName) ' Add the property to the list of dirty properties If Not ReadProperty(DirtyPropertiesProperty).Contains(propertyName) Then ReadProperty(DirtyPropertiesProperty).Add(propertyName) End If End Sub
Protected Overrides Sub MarkOld() MyBase.MarkOld() ' clear all dirty properties ReadProperty(DirtyPropertiesProperty).Clear() End Sub
Any help would be greatly appreciated.
Thanks,
Mike
Override PropertyHasChanged insted of OnPropertyChanged.
OnPropertyChanged is just to signal that a property may have changed (or staus has changed) so the UI can refresh its value and status.
PropertyHasChanged is called once per property that is changed by yhe user.
However - you may have rules that update other fields (lookup rules etc) so for managed properties you can also ask the FieldManager of the status for the backing field. The Rule system will now also mark updated managed properties (from AddOutValue) as Dirty.
You may also take a look at the extensions for backing fields that can check the old/new value to determine if the field is dirty. Code is available on http://cslacontrib.codeplex.com
If you are using WIndowsForms then make sure to set the proper CslaPropertyChangedMode. The default mode was changed for CSLA 4.x to be Xaml.
Thanks Jonny,
I never knew about the IsFieldDirty method on the FieldManager. And using the PropertyHasChanged override worked as well. Thanks again.
I converted the above into C#, but it doesn't want to compile. Are there changes available in 3.8 that aren't in 3.7 that would keep it from compiling?
VB.Net:
Public Shared ReadOnly DirtyPropertiesProperty As PropertyInfo(Of Collection(Of String)) = RegisterProperty(Of Collection(Of String))(Function(obj As MyBusinessBase(Of T)) obj.DirtyProperties, "Dirty Properties", New Collection(Of String))
C#:
public static readonly PropertyInfo<List<string>> DirtyPropertiesProperty = RegisterProperty<List<string>>((BusinessBase<T> obj) => obj.DirtyProperties, "Dirty Properties", new List<string>());
Also tried:
public static readonly PropertyInfo<List<string>> DirtyPropertiesProperty = RegisterProperty<List<string>>(Expression<Func<T, object>> T.DirtyProperties, "Dirty Properties", new List<string>(), RelationshipTypes.LazyLoad);
I get the "Invalid expression term 'object'" error on compile.
Thanks in advance for any light that can be shed on this.
Kelly.
First - you should nor use the basic List<> for a registered property as this is not serializable by the new MobileSerializer (or in SL or WP). You may use the MobileList<> class or create your own business list class.
This code works in C#:
public static readonly PropertyInfo<MobileList<string>> DirtyPropertiesProperty = RegisterProperty<MobileList<string>>(c => c.DirtyProperties, "Dirty Properties", new MobileList<string>(), RelationshipTypes.LazyLoad); public MobileList<string> DirtyProperties { get { return GetProperty(DirtyPropertiesProperty); } }
And in VB.NET:
Public Shared ReadOnly DirtyPropertiesProperty As PropertyInfo(Of MobileList(Of String)) = _
RegisterProperty(Of MobileList(Of String))(Function(c) c.DirtyProperties, "Dirty Properties", New MobileList(Of String)(), RelationshipTypes.LazyLoad) Public ReadOnly Property DirtyProperties() As MobileList(Of String) Get Return GetProperty(DirtyPropertiesProperty) End Get End Property
Copyright (c) Marimer LLC