Hi,
I am using CSLA 4 and Silverlight 4. I have an object graph with the following structure: Root - ChildList - Child. There is a business rule on my root object that needs to add a new child object to the child list. The problem I have is that ChildList.AddNew has different implementations on SL and .NET. In .NET I can just call AddNew and it will synchronously return my new object. The SL implementation just returns void and adds the new object to the collection asynchronously.
Does this mean that any rule that adds something to a collection MUST be async? If so, what is the best way to wire up the event handler to the CollectionChanged event on the collection? If I do it in the rule, then an additional handler gets wired up every time the rule runs.
Hi, when calling AddNew from Sl client , it doesnt return object .
as i think in SL client if you want to catch the added object for some reason you have to use the (( AddedNew (event)))
when evert you rule being call in the Execute method you have to do the following code :
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (Root)context.Target;
target.YourChildListProperty.AddedNew-=YourCatchMethod_AddedNew;
target.YourChildProperty.AddedNew+=new EventHandler<Csla.Core.AddedNewEventArgs<ChildList>>(YourCatchMethod_AddedNew);
}
the YourCatchMethod_AddedNew will contain parameter e if you want to catch the added new object .
Notice the reason why you use (
target.YourChildListProperty.AddedNew-=YourCatchMethod_AddedNew;) before the += because when your rule called more than once the method will be call two time or three ...... ihope this is what you were looking for
I had a similar problem to what you describe, but not with a business rule, I needed to add an object synchronously.
The way I solved it was to instantiate a new child object and then add it to the collection using the .add routine passing in the object I just created, thats the only way I could think of doing it.
Dim oNote as Note = New Note
NoteCollection.Add(oNote)
Dont know if that can help you or not?
AddNew on Silverlight has to be (potentially) async, because it is likely that you'll use the data portal to create the new child, and of course the data portal is async.
Of course AddNew is really there to support data binding scenarios, mostly around adding items to a datagrid or other UI list control. If you are adding items purely through code there's certainly no requirement to use AddNew and Craig's suggestion is a good one.
The only drawback to Craig's suggestion is that it doesn't use the data portal, which means you won't get some automatic behaviors like making your new object run its rules on creation, and of course you have no way to initialize the object with default values like you do when using the data portal's BeginCreate method.
The technique I use for this scenario is as follows:
In list add method
Public MyListItem AddNewMyListItem()
{
MyListItem newItem = MyListItem.NewMyListItem();
this.Add(newItem);
OnAddedNew(newItem);
return newItem;
}
In your child class's factory method (NewMyListItem) you can call return DataPortal.CreateChild<NewMyListItem>(), so you can follow the same factory patter there.
Thanks everybody for the ideas! I got the rule working by adding a new factory method to my child item object. I didn't use the constructor as my .NET constructors are private (my understanding was that the only reason for a public constructor was for SL serialization?) In any case, the factory method works fine in both SL and .NET.
I still have a few issues with the async rule:
1 - I cannot get the AddedNew event to fire, only the CollectionChanged event. Is this because I have to fire it myself (as in Sergey's example)?
2 - How can I pass (or access) the RuleContext in my event handler? I need to be able to call context.Complete() otherwise my property will stay in the busy state indefinitely....my rule will never finish.
Yes, your AddNew implementation must call OnAddedNew to indicate that the async (or sync) process is complete.
Copyright (c) Marimer LLC