using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Windows.Forms; using System.Globalization; using System.Drawing; using System.Security; using System.Reflection; using System.Collections; using System.ComponentModel.Design.Serialization; namespace DevComponents.DotNetBar { /// /// Defines class which described single binding. /// [TypeConverter(typeof(BindingDefConverer)), DesignTimeVisible(false), ToolboxItem(false)] public class BindingDef : INotifyPropertyChanged { #region Dependency Properties & Events public event DataConvertEventHandler Format; /// /// Raises Format event. /// /// Provides event arguments. protected virtual void OnFormat(DataConvertEventArgs e) { DataConvertEventHandler handler = Format; if (handler != null) handler(this, e); } #endregion #region Constructor /// /// Initializes a new instance of the BindingDef class. /// public BindingDef() { } /// /// Initializes a new instance of the BindingDef class. /// /// /// public BindingDef(string propertyName, string dataMember) { _PropertyName = propertyName; _PropertyPath = propertyName.Split('.'); _DataMember = dataMember; _BindingMemberInfo = new BindingMemberInfo(dataMember); } #endregion #region Implementation /// /// Updates specified item PropertyName with the data from data object property specified by DataMember. /// /// Item to set PropertyName on. /// Data to retrieve DataMember value from. public void Update(object item, object data) { Update(null, item, data); } /// /// Updates specified item PropertyName with the data from data object property specified by DataMember. /// /// CurrencyManager to use /// Item to set PropertyName on. /// Data to retrieve DataMember value from. public void Update(ItemVisualGenerator generator, object item, object data) { string propertyName = _PropertyName; if (item is BaseItem && _PropertyPath.Length > 1) { // Dig into child items BaseItem parent = (BaseItem)item; for (int i = 0; i < _PropertyPath.Length - 1; i++) { parent = parent.SubItems[_PropertyPath[i]]; } item = parent; propertyName = _PropertyPath[_PropertyPath.Length - 1]; } PropertyInfo targetProp = item.GetType().GetProperty(propertyName); if (targetProp.PropertyType == typeof(string)) targetProp.SetValue(item, GetDataText(generator, data, _DataMember), null); else targetProp.SetValue(item, GetDataValue(generator, data, _DataMember, GetPropertyValue(generator, data, _DataMember)), null); } private static TypeConverter stringTypeConverter; private string GetDataText(ItemVisualGenerator generator, object data, string fieldName) { object propertyValue = GetPropertyValue(generator, data, fieldName); return GetDataText(generator, data, fieldName, propertyValue); } private string GetDataText(ItemVisualGenerator generator, object data, string fieldName, object propertyValue) { if (!_FormattingEnabled) { if (data == null) { return string.Empty; } if (propertyValue == null) { return ""; } return Convert.ToString(propertyValue, CultureInfo.CurrentCulture); } DataConvertEventArgs e = new DataConvertEventArgs(propertyValue, typeof(string), data, fieldName); this.OnFormat(e); if ((e.Value != data) && (e.Value is string)) { return (string)e.Value; } if (stringTypeConverter == null) { stringTypeConverter = TypeDescriptor.GetConverter(typeof(string)); } try { return (string)FormatHelper.FormatObject(propertyValue, typeof(string), generator.GetFieldConverter(fieldName), stringTypeConverter, _FormatString, _FormatInfo, null, DBNull.Value); } catch (Exception ex) { if (ex is SecurityException || IsCriticalException(ex)) { throw; } return ((propertyValue != null) ? Convert.ToString(data, CultureInfo.CurrentCulture) : ""); } } private object GetDataValue(ItemVisualGenerator generator, object data, string fieldName, object propertyValue) { if (!_FormattingEnabled) { return propertyValue; } DataConvertEventArgs e = new DataConvertEventArgs(propertyValue, typeof(object), data, fieldName); this.OnFormat(e); return e.Value; } private static bool IsCriticalException(Exception ex) { return (((((ex is NullReferenceException) || (ex is StackOverflowException)) || ((ex is OutOfMemoryException) || (ex is System.Threading.ThreadAbortException))) || ((ex is ExecutionEngineException) || (ex is IndexOutOfRangeException))) || (ex is AccessViolationException)); } private object GetPropertyValue(ItemVisualGenerator generator, object data, string fieldName) { if ((data != null) && (fieldName.Length > 0)) { try { PropertyDescriptor descriptor = null; if (generator.DataManager != null) { descriptor = generator.DataManager.GetItemProperties().Find(fieldName, true); } if(descriptor == null) { descriptor = TypeDescriptor.GetProperties(data).Find(fieldName, true); } if (descriptor != null) { data = descriptor.GetValue(data); } } catch { } } if (data == DBNull.Value && _NullValue != null) return _NullValue; return data; } #endregion #region Properties private string[] _PropertyPath = new string[0]; private string _PropertyName = ""; /// /// Gets or sets the property name binding is attached to. /// [DefaultValue(""), Category("Data"), Description("Indicates property name binding is attached to.")] public string PropertyName { get { return _PropertyName; } set { if (value != _PropertyName) { string oldValue = _PropertyName; _PropertyName = value; OnPropertyNameChanged(oldValue, value); } } } /// /// Called when PropertyName property has changed. /// /// Old property value /// New property value protected virtual void OnPropertyNameChanged(string oldValue, string newValue) { _PropertyPath = newValue.Split('.'); OnPropertyChanged(new PropertyChangedEventArgs("PropertyName")); } /// /// Gets the reference to BindingMemberInfo created based on DataMember. /// [Browsable(false)] public BindingMemberInfo BindingMemberInfo { get { return _BindingMemberInfo; } } private BindingMemberInfo _BindingMemberInfo; private string _DataMember = ""; /// /// Gets or sets the data member name which holds data that PropertyName is populated with. /// [DefaultValue(""), Category("Data"), Description("Indicates data member name which holds data that PropertyName is populated with.")] public string DataMember { get { return _DataMember; } set { if (value == null) value = ""; if (value != _DataMember) { string oldValue = _DataMember; _DataMember = value; OnDataMemberChanged(oldValue, value); } } } /// /// Called when DataMember property has changed. /// /// Old property value /// New property value protected virtual void OnDataMemberChanged(string oldValue, string newValue) { if (!string.IsNullOrEmpty(newValue)) _BindingMemberInfo = new BindingMemberInfo(newValue); else _BindingMemberInfo = new BindingMemberInfo(); OnPropertyChanged(new PropertyChangedEventArgs("DataMember")); } private bool _FormattingEnabled = false; /// /// Gets or sets whether type conversion and formatting is applied to the property data. /// [DefaultValue(false), Category("Data"), Description("Indicates whether type conversion and formatting is applied to the property data.")] public bool FormattingEnabled { get { return _FormattingEnabled; } set { if (value != _FormattingEnabled) { bool oldValue = _FormattingEnabled; _FormattingEnabled = value; OnFormattingEnabledChanged(oldValue, value); } } } /// /// Called when FormattingEnabled property has changed. /// /// Old property value /// New property value protected virtual void OnFormattingEnabledChanged(bool oldValue, bool newValue) { OnPropertyChanged(new PropertyChangedEventArgs("FormattingEnabled")); } private string _FormatString = ""; /// /// Gets or sets format specifier characters that indicate how a value is to be displayed. /// For more information, see Formatting Overview: http://msdn.microsoft.com/en-us/library/26etazsy%28v=vs.71%29.aspx /// [DefaultValue(""), Category("Data"), Description("Indicates format specifier characters that indicate how a value is to be displayed.")] public string FormatString { get { return _FormatString; } set { if (value != _FormatString) { string oldValue = _FormatString; _FormatString = value; OnFormatStringChanged(oldValue, value); } } } /// /// Called when FormatString property has changed. /// /// Old property value /// New property value protected virtual void OnFormatStringChanged(string oldValue, string newValue) { OnPropertyChanged(new PropertyChangedEventArgs("FormatString")); } private IFormatProvider _FormatInfo = null; /// /// Gets or sets the IFormatProvider that provides custom formatting behavior. /// [DefaultValue(null), Category("Data"), Description("Indicates IFormatProvider that provides custom formatting behavior.")] public IFormatProvider FormatInfo { get { return _FormatInfo; } set { if (value != _FormatInfo) { IFormatProvider oldValue = _FormatInfo; _FormatInfo = value; OnFormatInfoChanged(oldValue, value); } } } /// /// Called when FormatInfo property has changed. /// /// Old property value /// New property value protected virtual void OnFormatInfoChanged(IFormatProvider oldValue, IFormatProvider newValue) { OnPropertyChanged(new PropertyChangedEventArgs("FormatInfo")); } private object _NullValue = null; /// /// Gets or sets the Object to be set as the target property when the data source contains a DBNull value. /// The data source must contain DBNull for the NullValue property to be correctly applied. /// If the data source type is a type such as a string or integer the value of the NullValue property will be ignored. /// Also, the NullValue property is ignored if it is set to null. /// [DefaultValue(null), Category("Data"), Description("Indicates Object to be set as the control property when the data source contains a DBNull value. ")] [System.ComponentModel.TypeConverter(typeof(System.ComponentModel.StringConverter))] public object NullValue { get { return _NullValue; } set { if (value != _NullValue) { object oldValue = _NullValue; _NullValue = value; OnNullValueChanged(oldValue, value); } } } /// /// Called when NullValue property has changed. /// /// Old property value /// New property value protected virtual void OnNullValueChanged(object oldValue, object newValue) { OnPropertyChanged(new PropertyChangedEventArgs("NullValue")); } #endregion #region INotifyPropertyChanged Members /// /// Raises the PropertyChanged event. /// /// Provides event arguments. protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, e); } /// /// Occurs when property on BindingDef object has changed. /// [Description("Occurs when property on BindingDef object has changed.Occurs when property on BindingDef object has changed.")] public event PropertyChangedEventHandler PropertyChanged; #endregion } /// /// Represents the method that will handle converting for bindings. /// /// /// public delegate void DataConvertEventHandler(object sender, DataConvertEventArgs e); public class DataConvertEventArgs : ConvertEventArgs { // Fields private object _DataItem; // Methods public DataConvertEventArgs(object value, Type desiredType, object dataItem, string fieldName) : base(value, desiredType) { _DataItem = dataItem; _FieldName = fieldName; } /// /// Gets the reference to the item being converted. /// public object DataItem { get { return _DataItem; } } private string _FieldName = ""; /// /// Get the reference to the name of the field or property on the item that needs conversion. /// public string FieldName { get { return _FieldName; } } } /// /// Represents BindingDefConverer converter. /// public class BindingDefConverer : TypeConverter { /// /// Creates new instance of the class. /// public BindingDefConverer() { } /// /// Checks whether conversion can be made to specified type. /// /// Context Information. /// Destination type. /// public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(InstanceDescriptor)) return true; return base.CanConvertTo(context, destinationType); } /// /// Converts object to specified type. /// /// Context information. /// Culture information. /// Object to convert. /// Destination type. /// Object converted to destination type. public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == null) throw new ArgumentNullException("destinationType"); if ((destinationType == typeof(InstanceDescriptor)) && (value is BindingDef)) { BindingDef info = (BindingDef)value; Type[] constructorParams = null; MemberInfo constructorMemberInfo = null; object[] constructorValues = null; constructorParams = new Type[] { typeof(string), typeof(string) }; constructorMemberInfo = typeof(BindingDef).GetConstructor(constructorParams); constructorValues = new object[] { info.PropertyName, info.DataMember }; if (constructorMemberInfo != null) { return new InstanceDescriptor(constructorMemberInfo, constructorValues); } } return base.ConvertTo(context, culture, value, destinationType); } } }