public static Type getEventHandlerType(object instance, string eventName){
return instance.GetType ().GetEvent (eventName).EventHandlerType;
}
+ public static void setValueWithReflexion(object dest, object value, string destMember){
+ Type destType = null;
+ Type origType = null;
+ object convertedVal = null;
+
+ MemberInfo miDest = getMemberInfoWithReflexion (dest, destMember);
+
+ if (miDest == null) {
+ Debug.WriteLine ("Reverse template binding error: " + destMember + " not found in " + dest);
+ return;
+ }
+
+ if (miDest.MemberType == MemberTypes.Property)
+ destType =(miDest as PropertyInfo).PropertyType;
+ else if (miDest.MemberType == MemberTypes.Field)
+ destType =(miDest as FieldInfo).FieldType;
+
+ if (value != null) {
+ origType = value.GetType ();
+ if (destType.IsAssignableFrom (origType))
+ convertedVal = Convert.ChangeType (value, destType);
+ else if (origType.IsPrimitive & destType.IsPrimitive)
+ convertedVal = GetConvertMethod (destType).Invoke (null, new Object[] { value });
+ else
+ convertedVal = getImplicitOp (origType, destType).Invoke (value, null);
+ }
+
+ if (miDest.MemberType == MemberTypes.Property)
+ (miDest as PropertyInfo).SetValue (dest, convertedVal);
+ else if (miDest.MemberType == MemberTypes.Field)
+ (miDest as FieldInfo).SetValue (dest, convertedVal);
+ }
public static object getValueWithReflexion(object instance, MemberInfo mi){
object tmp = null;
Type dstType = null;
break;
}
for (int i = 0; i < orig.Count - ptr; i++)
- il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("Parent").GetGetMethod ());
+ il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("LogicalParent").GetGetMethod ());
while (ptr < dest.Count) {
emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index);
ptr++;
MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
if (multiDel != null) {
foreach (Delegate d in multiDel.GetInvocationList()) {
- if (d.Method.Name == delegateName)
+ if (d.Method.Name == delegateName) {
eiEvt.RemoveEventHandler (instance, d);
+ #if DEBUG_BINDING
+ Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
+ #endif
+ }
}
}
}
MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
if (multiDel != null) {
foreach (Delegate d in multiDel.GetInvocationList()) {
- if (d.Target == target)
+ if (d.Target == target) {
eiEvt.RemoveEventHandler (instance, d);
+ #if DEBUG_BINDING
+ Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
+ #endif
+ }
}
}
}
public static Delegate compileDynEventHandler(EventInfo sourceEvent, string expression, NodeAddress currentNode = null){
+ #if DEBUG_BINDING
+ Debug.WriteLine ("\tCompile Event {0}: {1}", sourceEvent.Name, expression);
+ #endif
+
Type lopType = null;
if (currentNode == null)
return;
if (logicalParent != null)
(logicalParent as GraphicObject).DataSourceChanged -= onLogicalParentDataSourceChanged;
+ DataSourceChangeEventArgs dsce = new DataSourceChangeEventArgs (LogicalParent, null);
logicalParent = value;
+ dsce.NewDataSource = LogicalParent;
if (logicalParent != null)
(logicalParent as GraphicObject).DataSourceChanged += onLogicalParentDataSourceChanged;
+ onLogicalParentChanged (this, dsce);
}
}
[XmlIgnore]public virtual Rectangle ClientRectangle {
public event EventHandler<LayoutingEventArgs> LayoutChanged;
public event EventHandler<DataSourceChangeEventArgs> DataSourceChanged;
public event EventHandler<DataSourceChangeEventArgs> ParentChanged;
+ public event EventHandler<DataSourceChangeEventArgs> LogicalParentChanged;
#endregion
#region public properties
[XmlAttributeAttribute][DefaultValue(null)]
public virtual object DataSource {
set {
- if (dataSource == value)
+ if (DataSource == value)
return;
- DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (dataSource, value);
+ DataSourceChangeEventArgs dse = new DataSourceChangeEventArgs (DataSource, null);
dataSource = value;
+ dse.NewDataSource = DataSource;
OnDataSourceChanged (this, dse);
NotifyValueChanged ("DataSource", DataSource);
}
get {
- return dataSource == null ? LogicalParent == null ? null :
- LogicalParent is GraphicObject ?
- (LogicalParent as GraphicObject).DataSource : null : dataSource;
+ return dataSource == null ?
+ LogicalParent == null ? null :
+ LogicalParent is GraphicObject ? (LogicalParent as GraphicObject).DataSource : null :
+ dataSource;
}
}
protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){
- ILayoutable tmp = Parent;
- if (tmp == null) {
- Debug.WriteLine ("parent is null for: " + this.ToString ());
- return;
- }
- while (tmp != sender) {
- if (!(tmp as GraphicObject).localDataSourceIsNull) {
- OnDataSourceChanged (sender, e);
- return;
- }
- tmp = tmp.Parent;
- }
+ if (localDataSourceIsNull)
+ OnDataSourceChanged (this, e);
}
internal bool localDataSourceIsNull { get { return dataSource == null; } }
+ internal bool localLogicalParentIsNull { get { return logicalParent == null; } }
public virtual void OnDataSourceChanged(object sender, DataSourceChangeEventArgs e){
DataSourceChanged.Raise (this, e);
Disabled.Raise (this, e);
}
protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) {
- ParentChanged.Raise (sender, e);
+ ParentChanged.Raise (this, e);
+ if (logicalParent == null)
+ LogicalParentChanged.Raise (this, e);
+ }
+ protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) {
+ LogicalParentChanged.Raise (this, e);
}
-
#region IXmlSerializable
public virtual System.Xml.Schema.XmlSchema GetSchema ()
{
#region GraphicObject overrides
public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
{
- base.OnDataSourceChanged (sender, e);
+ base.OnDataSourceChanged (this, e);
foreach (GraphicObject g in children)
- if (g.localDataSourceIsNull)
+ if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
g.OnDataSourceChanged (sender, e);
}
public override GraphicObject FindByName (string nameToFind)
}
public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
{
- base.OnDataSourceChanged (sender, e);
+ base.OnDataSourceChanged (this, e);
if (child != null)
- if (child.localDataSourceIsNull)
+ if (child.localDataSourceIsNull & child.localLogicalParentIsNull)
child.OnDataSourceChanged (sender, e);
}
public override bool UpdateLayout (LayoutingType layoutType)
return _contentContainer == null ? null : _contentContainer.Child;
}
set {
+ if (Content != null) {
+ Content.LogicalParent = null;
+ _contentContainer.SetChild (null);
+ }
_contentContainer.SetChild(value);
+ if (value != null)
+ value.LogicalParent = this;
}
}
protected override void loadTemplate(GraphicObject template = null)
public event EventHandler<SelectionChangeEventArgs> SelectedItemChanged;
#endregion
- Group _list;
IList data;
int _selectedIndex;
Color selBackground, selForeground;
public virtual void AddItem(GraphicObject g){
items.AddChild (g);
+ g.LogicalParent = this;
NotifyValueChanged ("HasChildren", true);
}
public virtual void RemoveItem(GraphicObject g)
{
+ g.LogicalParent = null;
items.RemoveChild (g);
if (items.Children.Count == 0)
NotifyValueChanged ("HasChildren", false);
TargetNA = newTargetNA;
TargetName = "";
}
+
+ public override string ToString ()
+ {
+ string tmp = string.Format ("Source:{0}.{1}", SourceNA, SourceMember);
+ if (TwoWay)
+ tmp += " <=> ";
+ else
+ tmp += " <= ";
+
+ if (string.IsNullOrEmpty (TargetName))
+ tmp += string.Format ("Target:{0}.{1}]", TargetNA, TargetMember);
+ else
+ tmp += string.Format ("Target:{0}.{1}.{2}]", TargetNA, TargetName, TargetMember);
+ return tmp;
+ }
}
}
ctx.nodesStack.Pop ();
foreach (int idx in templateCachedDelegateIndices)
- ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("ParentChanged"));
+ ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("LogicalParentChanged"));
ctx.ResolveNamedTargets ();
/// </summary>
void compileAndStoreDynHandler (Context ctx, EventInfo sourceEvent, string expression)
{
- #if DEBUG_BINDING
- Debug.WriteLine ("\tCompile Event Source ");
- #endif
//store event handler dynamic method in instanciator
int dmIdx = cachedDelegates.Count;
cachedDelegates.Add (CompilerServices.compileDynEventHandler (sourceEvent, expression, ctx.CurrentNodeAddress));
il.Emit (OpCodes.Nop);
- emitRemoveOldDataSourceHandler(il, sourceEvent.Name, bindingDef.TargetMember);
+ emitRemoveOldDataSourceHandler (il, sourceEvent.Name, bindingDef.TargetMember, false);
//fetch method in datasource and test if it exist
il.Emit (OpCodes.Ldarg_2);//load new datasource
System.Reflection.Emit.Label finish = il.DefineLabel ();
il.Emit (OpCodes.Br, finish);
il.MarkLabel (cancel);
- il.EmitWriteLine (sourcePath + ": Handler method not found: " + bindingDef.TargetMember);
+ il.EmitWriteLine (string.Format ("Handler method '{0}' not found. {1}={2} ", bindingDef.TargetMember, sourceEvent.Name, expression));
il.MarkLabel (finish);
il.Emit (OpCodes.Ret);
if (piOrig != null)
origineType = piOrig.PropertyType;
foreach (MemberAddress ma in bindingCase.Value) {
- if (ma.Address.Count == 0)
- continue;//template binding
//first we have to load destination instance onto the stack, it is access
//with graphic tree functions deducted from nodes topology
il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
NodeAddress destination = ma.Address;
- CompilerServices.emitGetInstance (il, origine, destination);
+ if (destination.Count == 0){//template reverse binding
+ //fetch destination instance (which is the template root)
+ for (int j = 0; j < origine.Count ; j++)
+ il.Emit(OpCodes.Callvirt, typeof(GraphicObject).GetProperty("LogicalParent").GetGetMethod());
+ }else
+ CompilerServices.emitGetInstance (il, origine, destination);
- if (origineType != null){//prop less binding, no init requiered
+ if (origineType != null && destination.Count > 0){//else, prop less binding or reverse template bind, no init requiered
//for initialisation dynmeth, push destination instance loc_0 is root node in ctx
ctx.il.Emit(OpCodes.Ldloc_0);
CompilerServices.emitGetInstance (ctx.il, destination);
if (origineType == null)//property less binding, no init
CompilerServices.emitConvert (il, ma.Property.PropertyType);
- else {
+ else if (destination.Count > 0) {
if (origineType.IsValueType)
ctx.il.Emit(OpCodes.Box, origineType);
+
CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType);
CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType);
ctx.il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
+ } else {// reverse templateBinding
+ il.Emit (OpCodes.Ldstr, ma.memberName);//arg 3 of setValueWithReflexion
+ il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("setValueWithReflexion", BindingFlags.Static | BindingFlags.Public));
+ continue;
}
il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes
}
ILGenerator il = dm.GetILGenerator (256);
//create parentchanged dyn meth in parallel to have only one loop over bindings
- DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndParentChanged",
+ DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndLogicalParentChanged",
typeof (void),
CompilerServices.argsBoundDSChange, true);
ILGenerator ilPC = dmPC.GetILGenerator (256);
#region destination member affectations
foreach (MemberAddress ma in bindingCase.Value) {
- if (ma.Address.Count == 0)
+ if (ma.Address.Count == 0){
+ Debug.WriteLine("\t\tBUG: reverse template binding in normal template binding");
continue;//template binding
+ }
//first we try to get memberInfo of new parent, if it doesn't exist, it's a propery less binding
ilPC.Emit (OpCodes.Ldarg_2);//load new parent onto the stack for handler addition
ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
//store template bindings in instanciator
templateBinding = dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>));
- #region emit ParentChanged method
+ #region emit LogicalParentChanged method
//load new parent onto the stack for handler addition
ilPC.Emit (OpCodes.Ldarg_2);
cachedDelegates.Add(dmPC.CreateDelegate (CompilerServices.ehTypeDSChange, this));
#endregion
- ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("ParentChanged"));
+ ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("LogicalParentChanged"));
}
/// <summary>
/// create the valuechanged handler, the datasourcechanged handler and emit event handling
#endregion
/// <summary> Emits remove old data source event handler./summary>
- void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName){
+ void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){
System.Reflection.Emit.Label cancel = il.DefineLabel ();
il.Emit (OpCodes.Ldarg_2);//load old parent
il.Emit (OpCodes.Brfalse, cancel);//old parent is null
//remove handler
- il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource
- il.Emit (OpCodes.Ldfld, typeof (DataSourceChangeEventArgs).GetField ("OldDataSource"));
+ if (DSSide){//event is defined in the dataSource instance
+ il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource
+ il.Emit (OpCodes.Ldfld, typeof (DataSourceChangeEventArgs).GetField ("OldDataSource"));
+ }else//the event is in the source
+ il.Emit (OpCodes.Ldarg_1);//1st arg load old datasource
il.Emit (OpCodes.Ldstr, eventName);//2nd arg event name
il.Emit (OpCodes.Ldstr, delegateName);//3d arg: delegate name
il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("RemoveEventHandlerByName", BindingFlags.Static | BindingFlags.Public));
//TODO:parent is not reset to null because object will be added
//to ObjectToRedraw list, and without parent, it fails
GraphicObject g = GraphicTree [i];
+ g.DataSource = null;
g.Visible = false;
GraphicTree.RemoveAt (0);
}