Showing posts with label Silverlight. Show all posts
Showing posts with label Silverlight. Show all posts

Tuesday, February 8, 2011

Hirerachy Data Source - Using Fluent API convert flat data structure to hirerachy structure

It is often required to represent data in hirerachy structure. Over period of time, for several projects I had this requirement. In process of building this structure I observed a following common pattern/trend:

- Often times, to represent hirerachy structure, a custom class is created to hold original data.
- We will have recursive functions to select nodes at various levels and build tree structure.

Lets take a example of Employee. Employees are managed by Manager, who themselves are employees and also managed by some other employee.

Code:
class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public int ManagerID { get; set; }
}

And we have following class to represent Hirerachy structure
Code:

public interface INode
{
List ChildNodes { get; set; }
Object PayLoad { get; set; }
bool IsSelected { get; set; }
}
public class Node:INode
{
public List ChildNodes { get; set; }
public Object PayLoad { get; set; }
public Node()
{
ChildNodes = new List();
}
}

Before going further lets think of nature of conditions which we will be applying to Employee class to arrange it in hierarchy structure:

Employees who doesnt have any managerId are super employees like CEO who wont report to any other employee.
Condition for root employees: employee.ManagerID == default(int)
Employee child nodes will be those employees whose manager id is current employee's Id.
Condition which needs to be applied recursively is : parent.ID == child.ManagerID && child.ManagerID != default(int)

Using HirerachyData Structure you can compose your nodes as below:

List nodes = HirerachyDataSource
.ComposeHirerachyUsingStructure(persons) //Pass list of employees classes
.RootNodesFilter((p) => p.ManagerID == default(int)) //How root nodes to be selected.
.ChildNodeFilter((parent, child) => parent.ID == child.ManagerID && child.ManagerID != default(int)) //What condition to check recursively to build hirerachy
.UsingObjectBuilder((d) => new Node() { PayLoad = d }) //And finally how to build node.
.BuildHeirarchy();


Using this approach , you can compose how to select root, how to select nodes recursively, and even you can specify how to build final nodes (could be any type), due to which you can get the power to build any type of hirerachy structures with any properties (NOTE: code listing below is coupled to INode, but you can safely avoid that as Object builder will take care of instancing out of hirerachydatasource).

HirerachyDataSource code listing is below:
Code:

public class HirerachyDataSource
{
public static CompositionStructure ComposeHirerachyUsingStructure(List NodesList)
{
CompositionStructure structure = new CompositionStructure(NodesList);
return structure;
}



public class CompositionStructure
{
private List FlatStructure = new List();
Predicate rootNodeSelector;
Func ObjectBuilder;
Func childNodeSelector;
public CompositionStructure UsingObjectBuilder(Func nodeBuilder)
{
ObjectBuilder = nodeBuilder;
return this;
}
public ObservableCollection BuildHeirarchy()
{
return BuildNode();
}
internal CompositionStructure()
{

}
internal CompositionStructure(List nodes)
{
this.FlatStructure = nodes;
}

public CompositionStructure RootNodesFilter(Predicate rootNodesFilter)
{
rootNodeSelector = rootNodesFilter;
return this;
}
public CompositionStructure ChildNodeFilter(Func childNodeFilter)
{
childNodeSelector = childNodeFilter;
return this;
}
protected ObservableCollection BuildNode()
{
//INode node = new Node();
List nodes = (from a in FlatStructure
where rootNodeSelector(a)
select ObjectBuilder(a)).ToList();
if (nodes != null)
{
foreach (var item in nodes)
{
BuildNode(item);
}
}
return new ObservableCollection(nodes);
}

protected void BuildNode(INode node)
{
if (node != null)
{

List items= (from a in FlatStructure
where childNodeSelector((T)node.PayLoad, a)
select ObjectBuilder(a)).ToList();
node.ChildNodes = new ObservableCollection(items);
if (node.ChildNodes != null)
{
foreach (var item in node.ChildNodes)
{
BuildNode(item);
}
}
}
}
}
}

Monday, September 13, 2010

Silverlight - Using Fluent API to tie related async calls.

Introduction

In Silverlight all service calls are by default async calls. With ansync calls, you will be making a webservice call using one method and expects a call back in another method once you get a response from service. If you are using repository pattern you will be using same type of mechanism for communication between your view model and repositories.
In Async pattern there will be two related functions to accomplish a single task. One will initiate the task and another function will complete. Both these methods should work in tandem to accomplish single task.

And it will be highly error prone if you do not do proper event subscription & unsubscription. You also might want to take care of few common things like error handling, showing/hiding progress bar which will be common across all these calls. In this blog I will show you a interesting technique accomplishing same using elegant Fluent API solution.

Assume you have following repository class where you will define events once repositories webservice call complete it raises completed event, which will notify view model's completed event.
public class CustomerRepository

{

public event EventHandler<CustomEventArgs> GetCustomerNameCompleted;
public event EventHandler<CustomEventArgs> GetCustomerNameCompleted2;


public void GetCustomerName(string studyID)
{
WebServiceStub serviceStub = new WebServiceStub();
serviceStub.GetCustomerNameCompleted += (obj, args) =>
{

if (this.GetCustomerNameCompleted != null)
{
this.GetCustomerNameCompleted(this, args.GetCustomEventArgs());
}
};
serviceStub.GetCustomerNameByID(studyID);
}
public void GetCustomerName(string studyID, string Param1)
{
WebServiceStub serviceStub = new WebServiceStub();
serviceStub.GetCustomerNameCompleted2 += (obj, args) =>
{
if (this.GetCustomerNameCompleted2 != null)
{
this.GetCustomerNameCompleted2(this, args.GetCustomEventArgs());
}
};
serviceStub.GetCustomerName(studyID, Param1);
}

And in you View model


public void GetCustomers(int customerID)
{
repository.GetCustomerNameCompleted += repository_GetCustomerNameCompleted;

repository.GetCustomers(customerID)
}
void repository_GetCustomerNameCompleted(object sender, CustomEventArgs e)

{
repository.GetCustomerNameCompleted -= repository_GetCustomerNameCompleted;
}
You will be doing subscriptions and unsubscriptions throughout your silverlight ViewModels to repositories to fetch data. For each task you will have two methods in your view model.
You might be tempted to write completed method as anonymous, but it wont work as you have to unsubscribe once you are done. Otherwise subscriptions will keep on growing and you will get multiple callback for each call.

And if you forget to unsubscribe not only you will run into danger of memory leaks but buggy code. Instead of that if you can you use fluent API to make a call something as follows:

public void GetCustomer(string customerID)
{
StitchMethodFlow<string>

.Init
.WhenCalled(repository.GetCustomerName)
.WithParams(customerID)
.OnCompletionExecute((o,e)=>{//compelted;})
.CallBackSubscriptionProvider(repository.RegisterEventSubscription)
.StartExecution();
}

Above code looks simple, more maintainable, self explaining and code related to single task being done at single place not leaking to multiple methods. Now event subscription and Unsubscription are taken care by StitchMethodFlow.

You can download sample from here to see how it works. Demo is console application.

Monday, August 16, 2010

Silverlight - Property Value Synchronization between Two View Models

Recently I had been confronted with a design issue to keep two property values in two different View Models in Sync.



It is a simple issue, where you can subscribe to PropertyChange notifications and detect whenever interested property changes in Object1, set AnotherProperty's value in Another Object. And vice versa. To avoid recursive infinite loop situation, you can keep a flag which tracks direction of change and avoids this infinite loop.

But I wanted to solve this by keeping following constratints

1. I need to reuse this syncing logic wherever required in future.
2. Loosely Coupled.
3. No reflection, I want compile time support to detect any errors or most of them.
4. Should support FluentAPI for better usability.

Few assumption I made are
4. Both objects implements INotifyPropertyChanged event which raises event change notifications whenever property is changed.

Before discussing code, once developed you can use it like following to keep both objects in Sync.


//ViewModel which has a property
Class1 orgViewModel = new Class1();
//Another ViewModel which has another property.
Class2 anotherViewModel = new Class2();
//Sync API will be exposed by this SyncClass Which takes ViewModel types and property type.
SyncClass SyncClass = new SyncClass();

//Configure ViewModel with predicate to detect when property is changed and provide functions to read and write property values.
SyncClass.MonitorClass(orgViewModel, (propname) => { return propname == "MyVal"; })
.SetGetValue(()=>orgViewModel.MyVal)
.SetSetValue((i)=>orgViewModel.MyVal=i);
//Configure another ViewModel with predicate to detect when property is changed and provide functions to read and write property values.
SyncClass.MonitorAnotherClass(anotherViewModel, (propname) => { return propname == "AnotherVal"; })
.SetGetValue(()=>anotherViewModel.AnotherVal)
.SetSetValue((i1)=>anotherViewModel.AnotherVal=i1);
//Start Synchronization.
SyncClass.StartSync();

Once you configure you view models and property in above manner SynClass will auto sync two properties.

Code Listing

delegate void ValueChanged(object sender,EventArgs e);

class UsingClass
{
bool IsOriginator = false;
public event ValueChanged ObjectValueChanged;

T _MonitorObject;
Func _GetValue;
Action _SetValue;
Func<string,bool> _IsPropChanged;
public UsingClass(T MonitorObject,Func<string,bool> IsPropertyChanged)
{
_IsPropChanged = IsPropertyChanged;
_MonitorObject = MonitorObject;
INotifyPropertyChanged propChanged = _MonitorObject as INotifyPropertyChanged;
if (propChanged != null)
{
propChanged.PropertyChanged += (o1, e1) =>
{
if (_IsPropChanged(e1.Proeprtyname))
{
this.IsOriginator = true;
if (this.ObjectValueChanged != null)
{
this.ObjectValueChanged(this, new EventArgs());
}
}
};
}

}
public UsingClass SetGetValue(Func GetValue)
{
_GetValue=GetValue;
return this;
}
public T1 GetValue()
{
return _GetValue();
}
public void SetSetValue(Action SetValue)
{
this._SetValue = SetValue;
}
public void SetValue(T1 val1)
{
if (!IsOriginator)
{
_SetValue(val1);
}
else
{
IsOriginator =
false;
}
}
}

class SyncClass
{
UsingClass Object1;
UsingClass Object2;
public UsingClass MonitorClass(T MonitorObject,Func<string,bool> CheckPropertyChanged)
{
Object1 =
new UsingClass(MonitorObject,CheckPropertyChanged);
return Object1;

}
public UsingClass MonitorAnotherClass(T1 MonitorAnotherObject, Func<string, bool> CheckPropertyChanged)
{
Object2 =
new UsingClass(MonitorAnotherObject, CheckPropertyChanged);
return Object2;
}
public void StartSync()
{
Object1.ObjectValueChanged += (o, e) =>
{
Object2.SetValue(Object1.GetValue());
};
Object2.ObjectValueChanged += (o1, e1) =>
{
Object1.SetValue(Object2.GetValue());
};
}

}

I prepared a sample in Console Application which will be easy to execute and see how its working.

Click here to download sample application. You need VS 2010 to open this solution.

Hope you enjoyed this code crunch..

Thursday, July 29, 2010

Silverlight - Binding System uses Visual Tree

Recently I was working on a control where I need to re-arrange layout of passed in user controls, which alters visual tree structure. During this I found binding system relies on visual tree.

With example:


Page1
|
|--UserControl1
|--UserControl2
|--UserControl3

Transforms into

Custom Control
|
|-UserControl1
|-UserControl2
|-Page1
| |-UserControl3


Above page when passed to this custom control need to strip few controls and arrange in different layout. If Binding done at Page1 level, once you remove user controls to different place than this visual tree, bindings will not be resolved.

Thursday, July 15, 2010

Silverlight: Auto Notifying Delegate Commands

Prism provides Delegate Command equivalent to WPF's Delegate Command (ICommand) implementation in Silverlight. Using Delegate Command in Silverlight you can bind Commands to your view.
Whenever state of command changes, you will be doing something like this:

MyDelegateCmd.RaiseCanExecuteChanged()

which will notify binding system to requery binded command's CanExecute. In above approach your code will be scattered with RaiseCanExecteChanged across application. Instead you can use following class which will auto notify binding system.

public class AutoDelegateCommand<T> : DelegateCommand<T>
{

public INotifyPropertyChanged ViewModel { get; set; }
private void ListenForPropertyChagnedEventAndRequery(INotifyPropertyChanged presentationModel)
{
if (presentationModel != null)
{

presentationModel.PropertyChanged += (sender, args) =>
{
QueryCanExecute(args);
};
}
}

public void QueryCanExecute(PropertyChangedEventArgs args)
{
this.RaiseCanExecuteChanged();
}
}
public AutoDelegateCommand(INotifyPropertyChanged PresentationModel, Action executeMethod)
: base(executeMethod)
{
this.ViewModel = PresentationModel;
ListenForPropertyChagnedEventAndRequery(PresentationModel);
}
public AutoDelegateCommand(INotifyPropertyChanged PresentationModel, Action executeMethod, Func canExecuteMethod)
: base(executeMethod, canExecuteMethod)
{
this.ViewModel = PresentationModel;
ListenForPropertyChagnedEventAndRequery(PresentationModel);
}

}

By using above delegate command there will be no need to call requery in your view model. AutoDelegateCommand will subscribe to PropertyChanged event of passed in view model, and for each property change event it will raise RaiseCanExecute event.

Wednesday, July 14, 2010

Silverlight Profiling

You can do profiling of your silverlight 4 applications. Inside VS 2010 you will not be able to do it. You have to fire up VS Command Prompt and run following commands to perform profiling.
  1. VSPerfClrEnv /sampleon
  2. "C:\Program Files\Internet Explorer\iexplore.exe" http:\\youhostname\pathtosilverlightapplication
  3. VSPerfCmd /start:sample /output:ProfileTraceFileName /attach. You can Identify Process ID using Task Manager.
  4. Run you scenarios.
  5. VSPerfcmd /detach
  6. VSPerfCmd /shutdown
  7. VSPerfClrEnv /off

You can open your ProfileTraceFileName file in VS 2010 and see you code execution paths. But before you open you need to provide paths to MS Symbol Server and also path to your profiling application's pdb files to load symbols of your application. You can do this using VS 2010's menu "Debug->Settings", In settings option window, select symbols under Debug category. Ensure Microsoft Symbol server is selected, and also add path to your pdb files. After doing this, if you open Trace file you can see your code execution paths.