505 lines
19 KiB
C#
505 lines
19 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// Defines class which described single binding.
|
|
/// </summary>
|
|
[TypeConverter(typeof(BindingDefConverer)), DesignTimeVisible(false), ToolboxItem(false)]
|
|
public class BindingDef : INotifyPropertyChanged
|
|
{
|
|
#region Dependency Properties & Events
|
|
public event DataConvertEventHandler Format;
|
|
/// <summary>
|
|
/// Raises Format event.
|
|
/// </summary>
|
|
/// <param name="e">Provides event arguments.</param>
|
|
protected virtual void OnFormat(DataConvertEventArgs e)
|
|
{
|
|
DataConvertEventHandler handler = Format;
|
|
if (handler != null)
|
|
handler(this, e);
|
|
}
|
|
#endregion
|
|
|
|
#region Constructor
|
|
/// <summary>
|
|
/// Initializes a new instance of the BindingDef class.
|
|
/// </summary>
|
|
public BindingDef()
|
|
{
|
|
|
|
}
|
|
/// <summary>
|
|
/// Initializes a new instance of the BindingDef class.
|
|
/// </summary>
|
|
/// <param name="propertyName"></param>
|
|
/// <param name="dataMember"></param>
|
|
public BindingDef(string propertyName, string dataMember)
|
|
{
|
|
_PropertyName = propertyName;
|
|
_PropertyPath = propertyName.Split('.');
|
|
_DataMember = dataMember;
|
|
_BindingMemberInfo = new BindingMemberInfo(dataMember);
|
|
}
|
|
#endregion
|
|
|
|
#region Implementation
|
|
/// <summary>
|
|
/// Updates specified item PropertyName with the data from data object property specified by DataMember.
|
|
/// </summary>
|
|
/// <param name="item">Item to set PropertyName on.</param>
|
|
/// <param name="data">Data to retrieve DataMember value from.</param>
|
|
public void Update(object item, object data)
|
|
{
|
|
Update(null, item, data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates specified item PropertyName with the data from data object property specified by DataMember.
|
|
/// </summary>
|
|
/// <param name="dataManager">CurrencyManager to use</param>
|
|
/// <param name="item">Item to set PropertyName on.</param>
|
|
/// <param name="data">Data to retrieve DataMember value from.</param>
|
|
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 = "";
|
|
/// <summary>
|
|
/// Gets or sets the property name binding is attached to.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when PropertyName property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnPropertyNameChanged(string oldValue, string newValue)
|
|
{
|
|
_PropertyPath = newValue.Split('.');
|
|
OnPropertyChanged(new PropertyChangedEventArgs("PropertyName"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the reference to BindingMemberInfo created based on DataMember.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public BindingMemberInfo BindingMemberInfo
|
|
{
|
|
get
|
|
{
|
|
return _BindingMemberInfo;
|
|
}
|
|
}
|
|
|
|
private BindingMemberInfo _BindingMemberInfo;
|
|
private string _DataMember = "";
|
|
/// <summary>
|
|
/// Gets or sets the data member name which holds data that PropertyName is populated with.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when DataMember property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
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;
|
|
/// <summary>
|
|
/// Gets or sets whether type conversion and formatting is applied to the property data.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when FormattingEnabled property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnFormattingEnabledChanged(bool oldValue, bool newValue)
|
|
{
|
|
OnPropertyChanged(new PropertyChangedEventArgs("FormattingEnabled"));
|
|
|
|
}
|
|
|
|
private string _FormatString = "";
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when FormatString property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnFormatStringChanged(string oldValue, string newValue)
|
|
{
|
|
OnPropertyChanged(new PropertyChangedEventArgs("FormatString"));
|
|
|
|
}
|
|
|
|
private IFormatProvider _FormatInfo = null;
|
|
/// <summary>
|
|
/// Gets or sets the IFormatProvider that provides custom formatting behavior.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when FormatInfo property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnFormatInfoChanged(IFormatProvider oldValue, IFormatProvider newValue)
|
|
{
|
|
OnPropertyChanged(new PropertyChangedEventArgs("FormatInfo"));
|
|
|
|
}
|
|
|
|
private object _NullValue = null;
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when NullValue property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnNullValueChanged(object oldValue, object newValue)
|
|
{
|
|
OnPropertyChanged(new PropertyChangedEventArgs("NullValue"));
|
|
}
|
|
#endregion
|
|
|
|
#region INotifyPropertyChanged Members
|
|
/// <summary>
|
|
/// Raises the PropertyChanged event.
|
|
/// </summary>
|
|
/// <param name="e">Provides event arguments.</param>
|
|
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
|
|
{
|
|
PropertyChangedEventHandler handler = PropertyChanged;
|
|
if (handler != null) handler(this, e);
|
|
}
|
|
/// <summary>
|
|
/// Occurs when property on BindingDef object has changed.
|
|
/// </summary>
|
|
[Description("Occurs when property on BindingDef object has changed.Occurs when property on BindingDef object has changed.")]
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents the method that will handle converting for bindings.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the reference to the item being converted.
|
|
/// </summary>
|
|
public object DataItem
|
|
{
|
|
get
|
|
{
|
|
return _DataItem;
|
|
}
|
|
}
|
|
|
|
private string _FieldName = "";
|
|
/// <summary>
|
|
/// Get the reference to the name of the field or property on the item that needs conversion.
|
|
/// </summary>
|
|
public string FieldName
|
|
{
|
|
get { return _FieldName; }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents BindingDefConverer converter.
|
|
/// </summary>
|
|
public class BindingDefConverer : TypeConverter
|
|
{
|
|
/// <summary>
|
|
/// Creates new instance of the class.
|
|
/// </summary>
|
|
public BindingDefConverer() { }
|
|
|
|
/// <summary>
|
|
/// Checks whether conversion can be made to specified type.
|
|
/// </summary>
|
|
/// <param name="context">Context Information.</param>
|
|
/// <param name="destinationType">Destination type.</param>
|
|
/// <returns></returns>
|
|
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
{
|
|
if (destinationType == typeof(InstanceDescriptor))
|
|
return true;
|
|
return base.CanConvertTo(context, destinationType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts object to specified type.
|
|
/// </summary>
|
|
/// <param name="context">Context information.</param>
|
|
/// <param name="culture">Culture information.</param>
|
|
/// <param name="value">Object to convert.</param>
|
|
/// <param name="destinationType">Destination type.</param>
|
|
/// <returns>Object converted to destination type.</returns>
|
|
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);
|
|
}
|
|
}
|
|
}
|