using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.ComponentModel; namespace PresentationControls { /// /// Maintains an additional "Selected" and "Count" value for each item in a List. /// Useful in the CheckBoxComboBox. It holds a reference to the List[Index] Item and /// whether it is selected or not. /// It also caters for a Count, if needed. /// public class ListSelectionWrapper : List> { #region CONSTRUCTOR /// /// No property on the object is specified for display purposes, so simple ToString() operation /// will be performed. And no Counts will be displayed /// public ListSelectionWrapper(IEnumerable source) : this(source, false) { } /// /// No property on the object is specified for display purposes, so simple ToString() operation /// will be performed. /// public ListSelectionWrapper(IEnumerable source, bool showCounts) : base() { _Source = source; _ShowCounts = showCounts; if (_Source is IBindingList) ((IBindingList)_Source).ListChanged += new ListChangedEventHandler(ListSelectionWrapper_ListChanged); Populate(); } /// /// A Display "Name" property is specified. ToString() will not be performed on items. /// This is specifically useful on DataTable implementations, or where PropertyDescriptors are used to read the values. /// If a PropertyDescriptor is not found, a Property will be used. /// public ListSelectionWrapper(IEnumerable source, string usePropertyAsDisplayName) : this(source, false, usePropertyAsDisplayName) { } /// /// A Display "Name" property is specified. ToString() will not be performed on items. /// This is specifically useful on DataTable implementations, or where PropertyDescriptors are used to read the values. /// If a PropertyDescriptor is not found, a Property will be used. /// public ListSelectionWrapper(IEnumerable source, bool showCounts, string usePropertyAsDisplayName) : this(source, showCounts) { _DisplayNameProperty = usePropertyAsDisplayName; } #endregion #region PRIVATE PROPERTIES /// /// Is a Count indicator used. /// private bool _ShowCounts; /// /// The original List of values wrapped. A "Selected" and possibly "Count" functionality is added. /// private IEnumerable _Source; /// /// Used to indicate NOT to use ToString(), but read this property instead as a display value. /// private string _DisplayNameProperty = null; #endregion #region PUBLIC PROPERTIES /// /// When specified, indicates that ToString() should not be performed on the items. /// This property will be read instead. /// This is specifically useful on DataTable implementations, where PropertyDescriptors are used to read the values. /// public string DisplayNameProperty { get { return _DisplayNameProperty; } set { _DisplayNameProperty = value; } } /// /// Builds a concatenation list of selected items in the list. /// public string SelectedNames { get { string Text = ""; foreach (ObjectSelectionWrapper Item in this) if (Item.Selected) Text += ( string.IsNullOrEmpty(Text) ? String.Format("\"{0}\"", Item.Name) : String.Format(" & \"{0}\"", Item.Name)); return Text; } } /// /// Indicates whether the Item display value (Name) should include a count. /// public bool ShowCounts { get { return _ShowCounts; } set { _ShowCounts = value; } } #endregion #region HELPER MEMBERS /// /// Reset all counts to zero. /// public void ClearCounts() { foreach (ObjectSelectionWrapper Item in this) Item.Count = 0; } /// /// Creates a ObjectSelectionWrapper item. /// Note that the constructor signature of sub classes classes are important. /// /// /// private ObjectSelectionWrapper CreateSelectionWrapper(IEnumerator Object) { Type[] Types = new Type[] { typeof(T), this.GetType() }; ConstructorInfo CI = typeof(ObjectSelectionWrapper).GetConstructor(Types); if (CI == null) throw new Exception(String.Format( "The selection wrapper class {0} must have a constructor with ({1} Item, {2} Container) parameters.", typeof(ObjectSelectionWrapper), typeof(T), this.GetType())); object[] parameters = new object[] { Object.Current, this }; object result = CI.Invoke(parameters); return (ObjectSelectionWrapper)result; } /// /// /// /// /// public ObjectSelectionWrapper FindObjectWithItem(T Object) { return Find(new Predicate>( delegate(ObjectSelectionWrapper target) { return target.Item.Equals(Object); })); } /* public TSelectionWrapper FindObjectWithKey(object key) { return FindObjectWithKey(new object[] { key }); } public TSelectionWrapper FindObjectWithKey(object[] keys) { return Find(new Predicate( delegate(TSelectionWrapper target) { return ReflectionHelper.CompareKeyValues( ReflectionHelper.GetKeyValuesFromObject(target.Item, target.Item.TableInfo), keys); })); } public object[] GetArrayOfSelectedKeys() { List List = new List(); foreach (TSelectionWrapper Item in this) if (Item.Selected) { if (Item.Item.TableInfo.KeyProperties.Length == 1) List.Add(ReflectionHelper.GetKeyValueFromObject(Item.Item, Item.Item.TableInfo)); else List.Add(ReflectionHelper.GetKeyValuesFromObject(Item.Item, Item.Item.TableInfo)); } return List.ToArray(); } public T[] GetArrayOfSelectedKeys() { List List = new List(); foreach (TSelectionWrapper Item in this) if (Item.Selected) { if (Item.Item.TableInfo.KeyProperties.Length == 1) List.Add((T)ReflectionHelper.GetKeyValueFromObject(Item.Item, Item.Item.TableInfo)); else throw new LibraryException("This generator only supports single value keys."); // List.Add((T)ReflectionHelper.GetKeyValuesFromObject(Item.Item, Item.Item.TableInfo)); } return List.ToArray(); } */ private void Populate() { Clear(); /* for(int Index = 0; Index <= _Source.Count -1; Index++) Add(CreateSelectionWrapper(_Source[Index])); */ IEnumerator Enumerator = _Source.GetEnumerator(); if (Enumerator != null) while (Enumerator.MoveNext()) Add(CreateSelectionWrapper(Enumerator)); } #endregion #region EVENT HANDLERS private void ListSelectionWrapper_ListChanged(object sender, ListChangedEventArgs e) { switch (e.ListChangedType) { case ListChangedType.ItemAdded: Add(CreateSelectionWrapper((IEnumerator)((IBindingList)_Source)[e.NewIndex])); break; case ListChangedType.ItemDeleted: Remove(FindObjectWithItem((T)((IBindingList)_Source)[e.OldIndex])); break; case ListChangedType.Reset: Populate(); break; } } #endregion } }