moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using System.Reflection; moel@345: using System.ComponentModel; moel@345: moel@345: namespace Aga.Controls.Tree.NodeControls moel@345: { moel@345: public abstract class BindableControl : NodeControl moel@345: { moel@345: private struct MemberAdapter moel@345: { moel@345: private object _obj; moel@345: private PropertyInfo _pi; moel@345: private FieldInfo _fi; moel@345: moel@345: public static readonly MemberAdapter Empty = new MemberAdapter(); moel@345: moel@345: public Type MemberType moel@345: { moel@345: get moel@345: { moel@345: if (_pi != null) moel@345: return _pi.PropertyType; moel@345: else if (_fi != null) moel@345: return _fi.FieldType; moel@345: else moel@345: return null; moel@345: } moel@345: } moel@345: moel@345: public object Value moel@345: { moel@345: get moel@345: { moel@345: if (_pi != null && _pi.CanRead) moel@345: return _pi.GetValue(_obj, null); moel@345: else if (_fi != null) moel@345: return _fi.GetValue(_obj); moel@345: else moel@345: return null; moel@345: } moel@345: set moel@345: { moel@345: if (_pi != null && _pi.CanWrite) moel@345: _pi.SetValue(_obj, value, null); moel@345: else if (_fi != null) moel@345: _fi.SetValue(_obj, value); moel@345: } moel@345: } moel@345: moel@345: public MemberAdapter(object obj, PropertyInfo pi) moel@345: { moel@345: _obj = obj; moel@345: _pi = pi; moel@345: _fi = null; moel@345: } moel@345: moel@345: public MemberAdapter(object obj, FieldInfo fi) moel@345: { moel@345: _obj = obj; moel@345: _fi = fi; moel@345: _pi = null; moel@345: } moel@345: } moel@345: moel@345: #region Properties moel@345: moel@345: private bool _virtualMode = false; moel@345: [DefaultValue(false), Category("Data")] moel@345: public bool VirtualMode moel@345: { moel@345: get { return _virtualMode; } moel@345: set { _virtualMode = value; } moel@345: } moel@345: moel@345: private string _propertyName = ""; moel@345: [DefaultValue(""), Category("Data")] moel@345: public string DataPropertyName moel@345: { moel@345: get { return _propertyName; } moel@345: set moel@345: { moel@345: if (_propertyName == null) moel@345: _propertyName = string.Empty; moel@345: _propertyName = value; moel@345: } moel@345: } moel@345: moel@345: private bool _incrementalSearchEnabled = false; moel@345: [DefaultValue(false)] moel@345: public bool IncrementalSearchEnabled moel@345: { moel@345: get { return _incrementalSearchEnabled; } moel@345: set { _incrementalSearchEnabled = value; } moel@345: } moel@345: moel@345: #endregion moel@345: moel@345: public virtual object GetValue(TreeNodeAdv node) moel@345: { moel@345: if (VirtualMode) moel@345: { moel@345: NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); moel@345: OnValueNeeded(args); moel@345: return args.Value; moel@345: } moel@345: else moel@345: { moel@345: try moel@345: { moel@345: return GetMemberAdapter(node).Value; moel@345: } moel@345: catch (TargetInvocationException ex) moel@345: { moel@345: if (ex.InnerException != null) moel@345: throw new ArgumentException(ex.InnerException.Message, ex.InnerException); moel@345: else moel@345: throw new ArgumentException(ex.Message); moel@345: } moel@345: } moel@345: } moel@345: moel@345: public virtual void SetValue(TreeNodeAdv node, object value) moel@345: { moel@345: if (VirtualMode) moel@345: { moel@345: NodeControlValueEventArgs args = new NodeControlValueEventArgs(node); moel@345: args.Value = value; moel@345: OnValuePushed(args); moel@345: } moel@345: else moel@345: { moel@345: try moel@345: { moel@345: MemberAdapter ma = GetMemberAdapter(node); moel@345: ma.Value = value; moel@345: } moel@345: catch (TargetInvocationException ex) moel@345: { moel@345: if (ex.InnerException != null) moel@345: throw new ArgumentException(ex.InnerException.Message, ex.InnerException); moel@345: else moel@345: throw new ArgumentException(ex.Message); moel@345: } moel@345: } moel@345: } moel@345: moel@345: public Type GetPropertyType(TreeNodeAdv node) moel@345: { moel@345: return GetMemberAdapter(node).MemberType; moel@345: } moel@345: moel@345: private MemberAdapter GetMemberAdapter(TreeNodeAdv node) moel@345: { moel@345: if (node.Tag != null && !string.IsNullOrEmpty(DataPropertyName)) moel@345: { moel@345: Type type = node.Tag.GetType(); moel@345: PropertyInfo pi = type.GetProperty(DataPropertyName); moel@345: if (pi != null) moel@345: return new MemberAdapter(node.Tag, pi); moel@345: else moel@345: { moel@345: FieldInfo fi = type.GetField(DataPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); moel@345: if (fi != null) moel@345: return new MemberAdapter(node.Tag, fi); moel@345: } moel@345: } moel@345: return MemberAdapter.Empty; moel@345: } moel@345: moel@345: public override string ToString() moel@345: { moel@345: if (string.IsNullOrEmpty(DataPropertyName)) moel@345: return GetType().Name; moel@345: else moel@345: return string.Format("{0} ({1})", GetType().Name, DataPropertyName); moel@345: } moel@345: moel@345: public event EventHandler ValueNeeded; moel@345: private void OnValueNeeded(NodeControlValueEventArgs args) moel@345: { moel@345: if (ValueNeeded != null) moel@345: ValueNeeded(this, args); moel@345: } moel@345: moel@345: public event EventHandler ValuePushed; moel@345: private void OnValuePushed(NodeControlValueEventArgs args) moel@345: { moel@345: if (ValuePushed != null) moel@345: ValuePushed(this, args); moel@345: } moel@345: } moel@345: }