CSLA 4/Silverlight 4
I have a business rule on a BB object. This rule changes the property values for a handful of the BB's property. Sample property declaration –
public static PropertyInfo< double? > _latestValueInUCCProperty = RegisterProperty<double?>(p => p.LatestValueInUCC);
public double? LatestValueInUCC
{
get { return GetProperty(_latestValueInUCCProperty); }
set { LoadProperty(_latestValueInUCCProperty, value );
OnPropertyChanged(_latestValueInUCCProperty);
}
}
The reason I am using LoadProperty/OnPropertyChanged instead of SetProperty, is because I do not want these properties to ever change the IsDirty of the object but I still want them to refresh the UI.
I have added each of the properties that the rule changes to the Affected Properties
AffectedProperties.AddRange(new List<IPropertyInfo> { … ,_latestValueInUCCProperty, ... });
And in the “Execute” method of the rule , I change the property so..
context.AddOutValue(_latestValueInUCCProperty,dLatestValue);
Everything executes fine and the property changes its value but the UI never gets refreshed (using TwoWay binding). I was able to achieve this by calling context.Target.OnUnknownPropertyChanged(); but I believe that shouldn’t be necessary. Can anyone please explain why OnPropertyChanged may not be being invoked automatically on context.AddOutValue?
Thanks
Ranjini
We have unit tests like this too, but here's a sample app that demonstrates that PropertyChanged is raised for each property in the output list from a rule:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Csla; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var obj = new Test(); obj.PropertyChanged += (o, e) => { Console.WriteLine("PropertyChanged: " + e.PropertyName); }; obj.Value1 = "abc"; Console.WriteLine("value1: " + obj.Value1); Console.WriteLine("value2: " + obj.Value2); Console.ReadLine(); } } [Serializable] public class Test : BusinessBase<Test> { public static PropertyInfo<string> Value1Property = RegisterProperty<string>(c => c.Value1); public string Value1 { get { return GetProperty(Value1Property); } set { SetProperty(Value1Property, value); } } public static PropertyInfo<string> Value2Property = RegisterProperty<string>(c => c.Value2); public string Value2 { get { return GetProperty(Value2Property); } set { SetProperty(Value2Property, value); } } protected override void AddBusinessRules() { base.AddBusinessRules(); BusinessRules.AddRule(new MyRule()); } } public class MyRule : Csla.Rules.BusinessRule { public MyRule() { PrimaryProperty = Test.Value1Property; AffectedProperties.Add(Test.Value2Property); } protected override void Execute(Csla.Rules.RuleContext context) { context.AddOutValue("value 1 set"); context.AddOutValue(Test.Value2Property, "value 2 set"); } } }
The result of running this code is:
PropertyChanged: Value1
PropertyChanged: Value2
value1: value 1 set
value2: value 2 set
This is the expected result - PropertyChanged is raised for each affected property.
Thanks for your response.. I still am unable to figure out what it is that I am doing different .. but I will keep looking for it....
I have the same problem. Anyone?
Which UI technology are you using?
What is the setting of Csla.ApplicationContext.PropertyChangedMode?
Code from Csla.Core.BusinessBase:
protected virtual void PropertyHasChanged(Csla.Core.IPropertyInfo property)
{
MarkDirty(true);
var propertyNames = BusinessRules.CheckRules(property);
if (ApplicationContext.PropertyChangedMode == ApplicationContext.PropertyChangedModes.Windows)
OnPropertyChanged(property);
else
foreach (var name in propertyNames)
OnPropertyChanged(name);
}
Copyright (c) Marimer LLC