DotNet 4.8.1 build of DotNetBar
This commit is contained in:
562
PROMS/DotNetBar Source Code/ItemVisualGenerator.cs
Normal file
562
PROMS/DotNetBar Source Code/ItemVisualGenerator.cs
Normal file
@@ -0,0 +1,562 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.Collections;
|
||||
using System.Windows.Forms;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using DevComponents.DotNetBar.Primitives;
|
||||
|
||||
namespace DevComponents.DotNetBar
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides binding support for ItemPanel control.
|
||||
/// </summary>
|
||||
public class ItemVisualGenerator
|
||||
{
|
||||
#region Constructor
|
||||
private IBindingSupport _Parent = null;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ItemVisualGenerator class.
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public ItemVisualGenerator(IBindingSupport parent)
|
||||
{
|
||||
_Parent = parent;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation
|
||||
private object _DataSource = null;
|
||||
/// <summary>
|
||||
/// Gets or sets the data source for the ComboTree. Expected is an object that implements the IList or IListSource interfaces,
|
||||
/// such as a DataSet or an Array. The default is null.
|
||||
/// </summary>
|
||||
[AttributeProvider(typeof(IListSource)), Description("Indicates data source for the ComboTree."), Category("Data"), DefaultValue(null), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public object DataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return _DataSource;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (((value != null) && !(value is IList)) && !(value is IListSource))
|
||||
{
|
||||
throw new ArgumentException("Data type is not supported for complex data binding");
|
||||
}
|
||||
if (_DataSource != value)
|
||||
{
|
||||
if (DesignMode)
|
||||
_DataSource = value;
|
||||
else
|
||||
this.SetDataConnection(value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool DesignMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Parent is IComponent && ((IComponent)_Parent).Site != null)
|
||||
return ((IComponent)_Parent).Site.DesignMode;
|
||||
if (_Parent is Control && ((Control)_Parent).Site != null)
|
||||
return ((Control)_Parent).Site.DesignMode;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _InSetDataConnection = false;
|
||||
private void SetDataConnection(object newDataSource, bool force)
|
||||
{
|
||||
bool dataSourceChanged = _DataSource != newDataSource;
|
||||
|
||||
if (!_InSetDataConnection)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (force || dataSourceChanged)
|
||||
{
|
||||
_InSetDataConnection = true;
|
||||
IList list = (this.DataManager != null) ? this.DataManager.List : null;
|
||||
bool isDataManagerNull = this.DataManager == null;
|
||||
this.UnwireDataSource();
|
||||
_DataSource = newDataSource;
|
||||
this.WireDataSource();
|
||||
if (_IsDataSourceInitialized && !IsCustomCollection)
|
||||
{
|
||||
CurrencyManager manager = null;
|
||||
if (((newDataSource != null) && (_Parent.BindingContext != null)) && (newDataSource != Convert.DBNull))
|
||||
{
|
||||
string bindingPath = "";
|
||||
if (_Bindings != null && _Bindings.Count > 0)
|
||||
bindingPath = _Bindings[0].BindingMemberInfo.BindingPath;
|
||||
manager = (CurrencyManager)_Parent.BindingContext[newDataSource, bindingPath];
|
||||
}
|
||||
if (_DataManager != manager)
|
||||
{
|
||||
if (_DataManager != null)
|
||||
{
|
||||
_DataManager.ItemChanged -= new ItemChangedEventHandler(this.DataManager_ItemChanged);
|
||||
_DataManager.PositionChanged -= new EventHandler(this.DataManager_PositionChanged);
|
||||
}
|
||||
_DataManager = manager;
|
||||
if (_DataManager != null)
|
||||
{
|
||||
_DataManager.ItemChanged += new ItemChangedEventHandler(this.DataManager_ItemChanged);
|
||||
_DataManager.PositionChanged += new EventHandler(this.DataManager_PositionChanged);
|
||||
}
|
||||
}
|
||||
if (((_DataManager != null) && (dataSourceChanged)) && !ValidateDisplayMembers(_Bindings))
|
||||
{
|
||||
throw new ArgumentException("Wrong Bindings parameter", "newBindings");
|
||||
}
|
||||
if ((_DataManager != null && (dataSourceChanged || force))
|
||||
&& (dataSourceChanged || (force && ((list != _DataManager.List) || isDataManagerNull))))
|
||||
{
|
||||
DataManager_ItemChanged(_DataManager, null);
|
||||
}
|
||||
}
|
||||
_Converters.Clear();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_InSetDataConnection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateDisplayMembers(List<BindingDef> members)
|
||||
{
|
||||
if (members == null || members.Count == 0) return true;
|
||||
|
||||
foreach (BindingDef item in members)
|
||||
{
|
||||
if (item.BindingMemberInfo != null && !BindingMemberInfoInDataManager(item.BindingMemberInfo))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private bool BindingMemberInfoInDataManager(BindingMemberInfo bindingMemberInfo)
|
||||
{
|
||||
if (_DataManager != null)
|
||||
{
|
||||
PropertyDescriptorCollection itemProperties = _DataManager.GetItemProperties();
|
||||
int count = itemProperties.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!typeof(IList).IsAssignableFrom(itemProperties[i].PropertyType) && itemProperties[i].Name.Equals(bindingMemberInfo.BindingField))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
if (!typeof(IList).IsAssignableFrom(itemProperties[j].PropertyType) && (string.Compare(itemProperties[j].Name, bindingMemberInfo.BindingField, true, CultureInfo.CurrentCulture) == 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<BindingDef> _Bindings = new List<BindingDef>();
|
||||
public List<BindingDef> Bindings
|
||||
{
|
||||
get { return _Bindings; }
|
||||
set
|
||||
{
|
||||
if (value != _Bindings)
|
||||
{
|
||||
List<BindingDef> oldValue = _Bindings;
|
||||
_Bindings = value;
|
||||
OnBindingsChanged(oldValue, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when Bindings property has changed.
|
||||
/// </summary>
|
||||
/// <param name="oldValue">Old property value</param>
|
||||
/// <param name="newValue">New property value</param>
|
||||
protected virtual void OnBindingsChanged(List<BindingDef> oldValue, List<BindingDef> newValue)
|
||||
{
|
||||
//OnPropertyChanged(new PropertyChangedEventArgs("Bindings"));
|
||||
}
|
||||
|
||||
private CurrencyManager _DataManager = null;
|
||||
internal CurrencyManager DataManager
|
||||
{
|
||||
get
|
||||
{
|
||||
return _DataManager;
|
||||
}
|
||||
}
|
||||
private bool _IsDataSourceInitEventHooked = false;
|
||||
private void UnwireDataSource()
|
||||
{
|
||||
if (IsCustomCollection)
|
||||
{
|
||||
CustomCollection<object> col = (CustomCollection<object>)_DataSource;
|
||||
col.CollectionChanged -= CustomCollectionChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_DataSource is IComponent)
|
||||
{
|
||||
((IComponent) _DataSource).Disposed -= new EventHandler(DataSourceDisposed);
|
||||
}
|
||||
ISupportInitializeNotification dataSource = _DataSource as ISupportInitializeNotification;
|
||||
if ((dataSource != null) && _IsDataSourceInitEventHooked)
|
||||
{
|
||||
dataSource.Initialized -= new EventHandler(DataSourceInitialized);
|
||||
_IsDataSourceInitEventHooked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CustomCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
_Parent.BeginUpdate();
|
||||
try
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
int i = e.NewStartingIndex;
|
||||
foreach (object item in e.NewItems)
|
||||
{
|
||||
CreateVisualItem(_Parent.ItemsCollection, item, i, _Bindings);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
_Parent.ItemsCollection.RemoveAt(e.OldStartingIndex);
|
||||
//_Parent.ItemsCollection.RemoveAt(e.NewStartingIndex);
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Replace)
|
||||
{
|
||||
SetItemCore(e.NewStartingIndex, e.NewItems[0]);
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
RefreshItems();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_Parent.EndUpdate();
|
||||
}
|
||||
}
|
||||
private void DataSourceDisposed(object sender, EventArgs e)
|
||||
{
|
||||
this.SetDataConnection(null, true);
|
||||
}
|
||||
private bool _IsDataSourceInitialized = false;
|
||||
private void WireDataSource()
|
||||
{
|
||||
if (IsCustomCollection)
|
||||
{
|
||||
CustomCollection<object> col = (CustomCollection<object>) _DataSource;
|
||||
col.CollectionChanged += CustomCollectionChanged;
|
||||
_IsDataSourceInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_DataSource is IComponent)
|
||||
{
|
||||
((IComponent) _DataSource).Disposed += new EventHandler(DataSourceDisposed);
|
||||
}
|
||||
ISupportInitializeNotification dataSource = _DataSource as ISupportInitializeNotification;
|
||||
if ((dataSource != null) && !dataSource.IsInitialized)
|
||||
{
|
||||
dataSource.Initialized += new EventHandler(DataSourceInitialized);
|
||||
_IsDataSourceInitEventHooked = true;
|
||||
_IsDataSourceInitialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_IsDataSourceInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DataSourceInitialized(object sender, EventArgs e)
|
||||
{
|
||||
this.SetDataConnection(_DataSource, true);
|
||||
}
|
||||
|
||||
private void DataManager_ItemChanged(object sender, ItemChangedEventArgs e)
|
||||
{
|
||||
if (_Parent is Control)
|
||||
{
|
||||
Control parentControl = (Control)_Parent;
|
||||
if (parentControl.InvokeRequired)
|
||||
{
|
||||
parentControl.Invoke(new ItemChangedEventHandler(DataManager_ItemChanged), sender, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_DataManager != null)
|
||||
{
|
||||
if (e == null || e.Index == -1)
|
||||
{
|
||||
this.SetItemsCore(_DataManager.List);
|
||||
if (_Parent.AllowSelection)
|
||||
{
|
||||
_Parent.SelectedIndex = _DataManager.Position;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SetItemCore(e.Index, _DataManager.List[e.Index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DataManager_PositionChanged(object sender, EventArgs e)
|
||||
{
|
||||
if ((_DataManager != null) && _Parent.AllowSelection)
|
||||
{
|
||||
_Parent.SelectedIndex = _DataManager.Position;
|
||||
}
|
||||
}
|
||||
|
||||
private ICloneable _VisualTemplate = null;
|
||||
/// <summary>
|
||||
/// Gets or sets the visual template that is generated for each data item.
|
||||
/// </summary>
|
||||
public ICloneable VisualTemplate
|
||||
{
|
||||
get { return _VisualTemplate; }
|
||||
set
|
||||
{
|
||||
if (value != _VisualTemplate)
|
||||
{
|
||||
ICloneable oldValue = _VisualTemplate;
|
||||
_VisualTemplate = value;
|
||||
OnVisualTemplateChanged(oldValue, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when VisualTemplate property has changed.
|
||||
/// </summary>
|
||||
/// <param name="oldValue">Old property value</param>
|
||||
/// <param name="newValue">New property value</param>
|
||||
protected virtual void OnVisualTemplateChanged(ICloneable oldValue, ICloneable newValue)
|
||||
{
|
||||
//OnPropertyChanged(new PropertyChangedEventArgs("VisualTemplate"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, sets the specified array of objects in a collection in the derived class.
|
||||
/// </summary>
|
||||
/// <param name="items">An array of items.</param>
|
||||
protected virtual void SetItemsCore(IList items)
|
||||
{
|
||||
_Parent.BeginUpdate();
|
||||
|
||||
_Parent.ItemsCollection.Clear();
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
object item = items[i];
|
||||
CreateVisualItem(_Parent.ItemsCollection, item, i, _Bindings);
|
||||
}
|
||||
|
||||
_Parent.EndUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new item from template for the data.
|
||||
/// </summary>
|
||||
/// <param name="item">Data to create item for.</param>
|
||||
/// <returns>New instance of the BaseItem.</returns>
|
||||
private object CreateVisualItem(IList parent, object item, int itemIndex, List<BindingDef> bindings)
|
||||
{
|
||||
if(IsCustomCollection && item is ListBoxItem)
|
||||
{
|
||||
if (parent.Count <= itemIndex)
|
||||
parent.Add(item);
|
||||
else
|
||||
parent.Insert(itemIndex, item);
|
||||
|
||||
if (bindings.Count == 0) return item;
|
||||
SetVisualItemData(item, item, bindings, itemIndex);
|
||||
return item;
|
||||
}
|
||||
object visualItem = _VisualTemplate.Clone();
|
||||
|
||||
if (parent.Count <= itemIndex)
|
||||
parent.Add(visualItem);
|
||||
else
|
||||
parent.Insert(itemIndex, visualItem);
|
||||
|
||||
SetVisualItemData(visualItem, item, bindings, itemIndex);
|
||||
|
||||
DataItemVisualEventArgs eventArgs = new DataItemVisualEventArgs(visualItem, item);
|
||||
_Parent.InvokeDataNodeCreated(eventArgs);
|
||||
|
||||
return eventArgs.Visual;
|
||||
}
|
||||
|
||||
private void SetVisualItemData(object visualItem, object item, List<BindingDef> bindings, int bindingIndex)
|
||||
{
|
||||
PropertyInfo tagProperty = visualItem.GetType().GetProperty("Tag");
|
||||
if (tagProperty != null)
|
||||
tagProperty.SetValue(visualItem, new ItemBindingData(item, bindingIndex), null);
|
||||
|
||||
if (bindings.Count == 0)
|
||||
{
|
||||
if (visualItem is BaseItem)
|
||||
{
|
||||
if (item is string)
|
||||
((BaseItem)visualItem).Text = (string)item;
|
||||
else if (item != null)
|
||||
((BaseItem)visualItem).Text = item.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (BindingDef binding in bindings)
|
||||
{
|
||||
binding.Update(this, visualItem, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, sets the object with the specified index in the derived class.
|
||||
/// </summary>
|
||||
/// <param name="index">The array index of the object.</param>
|
||||
/// <param name="value">The object.</param>
|
||||
protected virtual void SetItemCore(int index, object value)
|
||||
{
|
||||
object visual = _Parent.ItemsCollection[index];
|
||||
if (visual == null) return;
|
||||
|
||||
_Parent.BeginUpdate();
|
||||
SetVisualItemData(visual, value, _Bindings, index);
|
||||
_Parent.EndUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, resynchronizes the item data with the contents of the data source.
|
||||
/// </summary>
|
||||
public virtual void RefreshItems()
|
||||
{
|
||||
_Parent.ItemsCollection.Clear();
|
||||
|
||||
if (_DataManager != null)
|
||||
{
|
||||
SetItemsCore(_DataManager.List);
|
||||
if (_Parent.AllowSelection)
|
||||
{
|
||||
_Parent.SelectedIndex = _DataManager.Position;
|
||||
}
|
||||
}
|
||||
else if (_DataSource is IList)
|
||||
SetItemsCore((IList)_DataSource);
|
||||
}
|
||||
|
||||
private Hashtable _Converters = new Hashtable();
|
||||
internal TypeConverter GetFieldConverter(string fieldName)
|
||||
{
|
||||
if (_Converters.ContainsKey(fieldName))
|
||||
return (TypeConverter)_Converters[fieldName];
|
||||
if (_DataManager != null)
|
||||
{
|
||||
PropertyDescriptorCollection itemProperties = _DataManager.GetItemProperties();
|
||||
if (itemProperties != null)
|
||||
{
|
||||
PropertyDescriptor descriptor = itemProperties.Find(fieldName, true);
|
||||
if (descriptor != null)
|
||||
{
|
||||
_Converters.Add(fieldName, descriptor.Converter);
|
||||
return descriptor.Converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool _CustomCollectionBinding = false;
|
||||
/// <summary>
|
||||
/// Indicates that generator should recognize when CustomCollection<T> is set as DataSource and bind to it instead of going through DataManager route.
|
||||
/// </summary>
|
||||
public bool CustomCollectionBinding
|
||||
{
|
||||
get { return _CustomCollectionBinding; }
|
||||
set
|
||||
{
|
||||
_CustomCollectionBinding = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public bool IsCustomCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
return _CustomCollectionBinding && _DataSource is CustomCollection<object>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IBindingSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets whether selection is allowed.
|
||||
/// </summary>
|
||||
bool AllowSelection { get;set;}
|
||||
/// <summary>
|
||||
/// Gets or sets the selected item index.
|
||||
/// </summary>
|
||||
int SelectedIndex { get;set;}
|
||||
/// <summary>
|
||||
/// Gets or sets the BindingContext.
|
||||
/// </summary>
|
||||
BindingContext BindingContext { get;set;}
|
||||
IList ItemsCollection { get; }
|
||||
void BeginUpdate();
|
||||
void EndUpdate();
|
||||
void InvokeDataNodeCreated(DataItemVisualEventArgs e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines delegate for data visual creation based events.
|
||||
/// </summary>
|
||||
public delegate void DataItemVisualEventHandler(object sender, DataItemVisualEventArgs e);
|
||||
/// <summary>
|
||||
/// Defines event arguments for data visual creation based events.
|
||||
/// </summary>
|
||||
public class DataItemVisualEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the visual that is created for data item.
|
||||
/// </summary>
|
||||
public object Visual = null;
|
||||
/// <summary>
|
||||
/// Gets the data-item node is being created for.
|
||||
/// </summary>
|
||||
public readonly object DataItem = null;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DataNodeEventArgs class.
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="dataItem"></param>
|
||||
public DataItemVisualEventArgs(object visual, object dataItem)
|
||||
{
|
||||
Visual = visual;
|
||||
DataItem = dataItem;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user