0
|
1 using System;
|
|
2 using System.Collections;
|
|
3 using System.ComponentModel;
|
|
4 using System.Drawing.Design;
|
|
5 using System.Drawing;
|
|
6 using System.Windows.Forms;
|
|
7
|
|
8 using BLToolkit.EditableObjects;
|
|
9 using BLToolkit.Reflection;
|
|
10
|
|
11 namespace BLToolkit.ComponentModel
|
|
12 {
|
|
13 /// <summary>
|
|
14 /// http://www.bltoolkit.net/Doc/ComponentModel/ObjectBinder.htm
|
|
15 /// </summary>
|
|
16 //[ComplexBindingProperties("DataSource", "DataMember")]
|
|
17 [ComplexBindingProperties("DataSource")]
|
|
18 [DefaultProperty("ItemType")]
|
|
19 [ToolboxItem(true)]
|
|
20 [ToolboxBitmap(typeof(ObjectBinder))]
|
|
21 public class ObjectBinder : Component, ITypedList, IBindingListView, ICancelAddNew
|
|
22 {
|
|
23 #region Constructors
|
|
24
|
|
25 static readonly EditableArrayList _empty = new EditableArrayList(typeof(object));
|
|
26
|
|
27 public ObjectBinder()
|
|
28 {
|
|
29 }
|
|
30
|
|
31 public ObjectBinder(IContainer container)
|
|
32 : this()
|
|
33 {
|
|
34 if (container != null)
|
|
35 container.Add(this);
|
|
36 }
|
|
37
|
|
38 #endregion
|
|
39
|
|
40 #region Public members
|
|
41
|
|
42 private object _dataSource;
|
|
43
|
|
44 [AttributeProvider(typeof(IListSource))]
|
|
45 [RefreshProperties(RefreshProperties.Repaint)]
|
|
46 [DefaultValue(null)]
|
|
47 [Category("Data")]
|
|
48 public object DataSource
|
|
49 {
|
|
50 get { return _dataSource; }
|
|
51 set
|
|
52 {
|
|
53 _dataSource = value;
|
|
54
|
|
55 if (value is Type) ItemType = (Type)value;
|
|
56 else if (value is BindingSource) DataSource = ((BindingSource)value).DataSource;
|
|
57 else if (value is IList) List = (IList)value;
|
|
58 else if (value is IListSource) List = ((IListSource)value).GetList();
|
|
59 else Object = value;
|
|
60 }
|
|
61 }
|
|
62
|
|
63 private Type _itemType;
|
|
64 [RefreshProperties(RefreshProperties.Repaint)]
|
|
65 [DefaultValue(null)]
|
|
66 [Category("Data")]
|
|
67 [TypeConverter(typeof(TypeTypeConverter))]
|
|
68 #if !CLIENTPROFILE
|
|
69 [Editor(typeof(Design.TypeEditor), typeof(UITypeEditor))]
|
|
70 #endif
|
|
71 public Type ItemType
|
|
72 {
|
|
73 get { return _itemType; }
|
|
74 set
|
|
75 {
|
|
76 _itemType = value;
|
|
77
|
|
78 List = null;
|
|
79
|
|
80 OnListChanged(ListChangedType.PropertyDescriptorChanged, -1);
|
|
81 }
|
|
82 }
|
|
83
|
|
84 private Type _objectViewType;
|
|
85 [RefreshProperties(RefreshProperties.Repaint)]
|
|
86 [DefaultValue(null)]
|
|
87 [Category("Data")]
|
|
88 [TypeConverter(typeof(TypeTypeConverter))]
|
|
89 #if !CLIENTPROFILE
|
|
90 [Editor(typeof(Design.ObjectViewTypeEditor), typeof(UITypeEditor))]
|
|
91 #endif
|
|
92 public Type ObjectViewType
|
|
93 {
|
|
94 get { return _objectViewType; }
|
|
95 set
|
|
96 {
|
|
97 _objectViewType = value;
|
|
98
|
|
99 List = null;
|
|
100
|
|
101 OnListChanged(ListChangedType.PropertyDescriptorChanged, -1);
|
|
102 }
|
|
103 }
|
|
104
|
|
105 private object _object;
|
|
106 [Browsable(false)]
|
|
107 [RefreshProperties(RefreshProperties.Repaint)]
|
|
108 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
109 public object Object
|
|
110 {
|
|
111 get { return _object; }
|
|
112 set
|
|
113 {
|
|
114 if (value == null)
|
|
115 {
|
|
116 List = null;
|
|
117 }
|
|
118 else
|
|
119 {
|
|
120 EditableArrayList list = new EditableArrayList(value.GetType(), 1);
|
|
121
|
|
122 list.Add(value, false);
|
|
123
|
|
124 List = list;
|
|
125 _object = value;
|
|
126 }
|
|
127 }
|
|
128 }
|
|
129
|
|
130 private bool _isListCreatedInternally;
|
|
131 private EditableArrayList _list = _empty;
|
|
132 [Browsable(false)]
|
|
133 [RefreshProperties(RefreshProperties.Repaint)]
|
|
134 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
135 public IList List
|
|
136 {
|
|
137 get { return _list; }
|
|
138 set
|
|
139 {
|
|
140 if (value == null)
|
|
141 {
|
|
142 if (_list != _empty)
|
|
143 _list.ListChanged -= ListChangedHandler;
|
|
144
|
|
145 _list = _itemType == null? _empty: new EditableArrayList(_itemType);
|
|
146 _isListCreatedInternally = true;
|
|
147 }
|
|
148 else
|
|
149 {
|
|
150 EditableArrayList list;
|
|
151
|
|
152 if (value is EditableArrayList)
|
|
153 {
|
|
154 list = (EditableArrayList)value;
|
|
155
|
|
156 _isListCreatedInternally = false;
|
|
157 }
|
|
158 else
|
|
159 {
|
|
160 if (value.Count != 0 && _itemType == null)
|
|
161 list = EditableArrayList.Adapter(value);
|
|
162 else
|
|
163 list = EditableArrayList.Adapter(_itemType, value);
|
|
164
|
|
165 _isListCreatedInternally = true;
|
|
166 }
|
|
167
|
|
168 if (_itemType == null)
|
|
169 {
|
|
170 _itemType = list.ItemType;
|
|
171 }
|
|
172 else
|
|
173 {
|
|
174 if (list.ItemType != _itemType && !list.ItemType.IsSubclassOf(_itemType))
|
|
175 throw new ArgumentException(string.Format(
|
|
176 "Item type {0} of the new list must be a subclass of {1}.",
|
|
177 list.ItemType,
|
|
178 _itemType));
|
|
179 }
|
|
180
|
|
181 if (_list != _empty)
|
|
182 {
|
|
183 _list.ListChanged -= ListChangedHandler;
|
|
184
|
|
185 if (_disposeList || (_isListCreatedInternally && _disposeCreatedList))
|
|
186 _list.Dispose();
|
|
187 }
|
|
188
|
|
189 _list = list;
|
|
190 }
|
|
191
|
|
192 if (_list != _empty)
|
|
193 _list.ListChanged += ListChangedHandler;
|
|
194
|
|
195 OnListChanged(ListChangedType.Reset, -1);
|
|
196 }
|
|
197 }
|
|
198
|
|
199 private bool _disposeList;
|
|
200 [DefaultValue(false)]
|
|
201 [Category("Behavior")]
|
|
202 [Description("Determines whether ObjectBinder will invoke underlying List's dispose when being itself disposed.")]
|
|
203 public bool DisposeList
|
|
204 {
|
|
205 get { return _disposeList; }
|
|
206 set { _disposeList = value; }
|
|
207 }
|
|
208
|
|
209 private bool _disposeCreatedList = true;
|
|
210 [DefaultValue(true)]
|
|
211 [Category("Behavior")]
|
|
212 [Description("Determines whether ObjectBinder will invoke underlying internally created List's dispose when being itself disposed")]
|
|
213 public bool DisposeCreatedList
|
|
214 {
|
|
215 get { return _disposeCreatedList; }
|
|
216 set { _disposeCreatedList = value; }
|
|
217 }
|
|
218
|
|
219 private bool _allowNew = true;
|
|
220 [DefaultValue(true)]
|
|
221 [Category("Behavior")]
|
|
222 [Description("Determines whether new items can be added to the list.")]
|
|
223 public bool AllowNew
|
|
224 {
|
|
225 get { return _allowNew && _list.AllowNew; }
|
|
226 set { _allowNew = value; }
|
|
227 }
|
|
228
|
|
229 private bool _allowEdit = true;
|
|
230 [DefaultValue(true)]
|
|
231 [Category("Behavior")]
|
|
232 [Description("Determines whether items in the list can be edited.")]
|
|
233 public bool AllowEdit
|
|
234 {
|
|
235 get { return _allowEdit && _list.AllowEdit; }
|
|
236 set { _allowEdit = value; }
|
|
237 }
|
|
238
|
|
239 private bool _allowRemove = true;
|
|
240 [DefaultValue(true)]
|
|
241 [Category("Behavior")]
|
|
242 [Description("Determines whether items can be removed from the list.")]
|
|
243 public bool AllowRemove
|
|
244 {
|
|
245 get { return _allowRemove && _list.AllowRemove; }
|
|
246 set { _allowRemove = value; }
|
|
247 }
|
|
248
|
|
249 private IsNullHandler _isNull;
|
|
250 [Browsable(false)]
|
|
251 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
252 public IsNullHandler IsNull
|
|
253 {
|
|
254 get { return _isNull; }
|
|
255 set { _isNull = value; }
|
|
256 }
|
|
257
|
|
258 bool IBindingList.AllowNew { get { return AllowNew; } }
|
|
259 bool IBindingList.AllowEdit { get { return AllowEdit; } }
|
|
260 bool IBindingList.AllowRemove { get { return AllowRemove; } }
|
|
261
|
|
262 #endregion
|
|
263
|
|
264 #region Protected Members
|
|
265
|
|
266 protected virtual void OnListChanged(ListChangedEventArgs e)
|
|
267 {
|
|
268 ListChangedEventHandler handler = (ListChangedEventHandler)Events[ListChangedEvent];
|
|
269 if (handler != null)
|
|
270 handler(this, e);
|
|
271 }
|
|
272
|
|
273 protected void OnListChanged(ListChangedType listChangedType, int newIndex)
|
|
274 {
|
|
275 OnListChanged(new ListChangedEventArgs(listChangedType, newIndex));
|
|
276 }
|
|
277
|
|
278 private void ListChangedHandler(object sender, ListChangedEventArgs e)
|
|
279 {
|
|
280 OnListChanged(e);
|
|
281 }
|
|
282
|
|
283 protected override void Dispose(bool disposing)
|
|
284 {
|
|
285 if (_list != _empty)
|
|
286 {
|
|
287 _list.ListChanged -= ListChangedHandler;
|
|
288
|
|
289 if (_disposeList || (_isListCreatedInternally && _disposeCreatedList))
|
|
290 _list.Dispose();
|
|
291 }
|
|
292
|
|
293 _list = _empty;
|
|
294
|
|
295 base.Dispose(disposing);
|
|
296 }
|
|
297
|
|
298 #endregion
|
|
299
|
|
300 #region ITypedList Members
|
|
301
|
|
302 private static readonly Hashtable _descriptors = new Hashtable();
|
|
303
|
|
304 PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
|
|
305 {
|
|
306 if (_itemType == null)
|
|
307 return new PropertyDescriptorCollection(new PropertyDescriptor[0]);
|
|
308
|
|
309 string key =
|
|
310 _itemType + "." +
|
|
311 (_objectViewType == null? string.Empty: _objectViewType.ToString()) + "." +
|
|
312 (_isNull == null? "0": "1");
|
|
313
|
|
314 if (listAccessors != null)
|
|
315 foreach (PropertyDescriptor pd in listAccessors)
|
|
316 key += "." + pd.Name;
|
|
317
|
|
318 PropertyDescriptorCollection pdc = (PropertyDescriptorCollection)_descriptors[key];
|
|
319
|
|
320 if (pdc == null)
|
|
321 {
|
|
322 pdc = _list.GetItemProperties(listAccessors, _objectViewType, _isNull, !DesignMode);
|
|
323
|
|
324 if (!DesignMode)
|
|
325 _descriptors[key] = pdc;
|
|
326 }
|
|
327
|
|
328 return pdc;
|
|
329 }
|
|
330
|
|
331 string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
|
|
332 {
|
|
333 return _list.GetListName(listAccessors);
|
|
334 }
|
|
335
|
|
336 #endregion
|
|
337
|
|
338 #region IBindingListView Members
|
|
339
|
|
340 bool IBindingListView.SupportsAdvancedSorting
|
|
341 {
|
|
342 get { return _list.SupportsAdvancedSorting; }
|
|
343 }
|
|
344
|
|
345 ListSortDescriptionCollection IBindingListView.SortDescriptions
|
|
346 {
|
|
347 get { return _list.SortDescriptions; }
|
|
348 }
|
|
349
|
|
350 void IBindingListView.ApplySort(ListSortDescriptionCollection sorts)
|
|
351 {
|
|
352 _list.ApplySort(sorts);
|
|
353 }
|
|
354
|
|
355 bool IBindingListView.SupportsFiltering
|
|
356 {
|
|
357 get { return _list.SupportsFiltering; }
|
|
358 }
|
|
359
|
|
360 string IBindingListView.Filter
|
|
361 {
|
|
362 get { return _list.Filter; }
|
|
363 set { _list.Filter = value; }
|
|
364 }
|
|
365
|
|
366 void IBindingListView.RemoveFilter()
|
|
367 {
|
|
368 _list.RemoveFilter();
|
|
369 }
|
|
370
|
|
371 #endregion
|
|
372
|
|
373 #region ICancelAddNew Members
|
|
374
|
|
375 void ICancelAddNew.CancelNew(int itemIndex)
|
|
376 {
|
|
377 _list.CancelNew(itemIndex);
|
|
378 }
|
|
379
|
|
380 void ICancelAddNew.EndNew(int itemIndex)
|
|
381 {
|
|
382 _list.EndNew(itemIndex);
|
|
383 }
|
|
384
|
|
385 #endregion
|
|
386
|
|
387 #region IBindingList Members
|
|
388
|
|
389 void IBindingList.AddIndex(PropertyDescriptor property)
|
|
390 {
|
|
391 _list.AddIndex(property);
|
|
392 }
|
|
393
|
|
394 object IBindingList.AddNew()
|
|
395 {
|
|
396 return _list.AddNew();
|
|
397 }
|
|
398
|
|
399 void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
|
|
400 {
|
|
401 _list.ApplySort(property, direction);
|
|
402 }
|
|
403
|
|
404 int IBindingList.Find(PropertyDescriptor property, object key)
|
|
405 {
|
|
406 return _list.Find(property, key);
|
|
407 }
|
|
408
|
|
409 bool IBindingList.IsSorted
|
|
410 {
|
|
411 get { return _list.IsSorted; }
|
|
412 }
|
|
413
|
|
414 private static readonly object ListChangedEvent = new object();
|
|
415
|
|
416 public event ListChangedEventHandler ListChanged
|
|
417 {
|
|
418 add { Events.AddHandler (ListChangedEvent, value); }
|
|
419 remove { Events.RemoveHandler(ListChangedEvent, value); }
|
|
420 }
|
|
421
|
|
422 void IBindingList.RemoveIndex(PropertyDescriptor property)
|
|
423 {
|
|
424 _list.RemoveIndex(property);
|
|
425 }
|
|
426
|
|
427 void IBindingList.RemoveSort()
|
|
428 {
|
|
429 _list.RemoveSort();
|
|
430 }
|
|
431
|
|
432 ListSortDirection IBindingList.SortDirection
|
|
433 {
|
|
434 get { return _list.SortDirection; }
|
|
435 }
|
|
436
|
|
437 PropertyDescriptor IBindingList.SortProperty
|
|
438 {
|
|
439 get { return _list.SortProperty; }
|
|
440 }
|
|
441
|
|
442 bool IBindingList.SupportsChangeNotification
|
|
443 {
|
|
444 get { return _list.SupportsChangeNotification; }
|
|
445 }
|
|
446
|
|
447 bool IBindingList.SupportsSearching
|
|
448 {
|
|
449 get { return _list.SupportsSearching; }
|
|
450 }
|
|
451
|
|
452 bool IBindingList.SupportsSorting
|
|
453 {
|
|
454 get { return _list.SupportsSorting; }
|
|
455 }
|
|
456
|
|
457 #endregion
|
|
458
|
|
459 #region IList Members
|
|
460
|
|
461 int IList.Add(object value)
|
|
462 {
|
|
463 return _list.Add(value);
|
|
464 }
|
|
465
|
|
466 void IList.Clear()
|
|
467 {
|
|
468 _list.Clear();
|
|
469 }
|
|
470
|
|
471 bool IList.Contains(object value)
|
|
472 {
|
|
473 return _list.Contains(value);
|
|
474 }
|
|
475
|
|
476 int IList.IndexOf(object value)
|
|
477 {
|
|
478 return _list.IndexOf(value);
|
|
479 }
|
|
480
|
|
481 void IList.Insert(int index, object value)
|
|
482 {
|
|
483 _list.Insert(index, value);
|
|
484 }
|
|
485
|
|
486 bool IList.IsFixedSize
|
|
487 {
|
|
488 get { return _list.IsFixedSize; }
|
|
489 }
|
|
490
|
|
491 bool IList.IsReadOnly
|
|
492 {
|
|
493 get { return _list.IsReadOnly; }
|
|
494 }
|
|
495
|
|
496 void IList.Remove(object value)
|
|
497 {
|
|
498 _list.Remove(value);
|
|
499 }
|
|
500
|
|
501 void IList.RemoveAt(int index)
|
|
502 {
|
|
503 _list.RemoveAt(index);
|
|
504 }
|
|
505
|
|
506 object IList.this[int index]
|
|
507 {
|
|
508 get { return index == -1? null: _list[index]; }
|
|
509 set { _list[index] = value; }
|
|
510 }
|
|
511
|
|
512 #endregion
|
|
513
|
|
514 #region ICollection Members
|
|
515
|
|
516 void ICollection.CopyTo(Array array, int index)
|
|
517 {
|
|
518 _list.CopyTo(array, index);
|
|
519 }
|
|
520
|
|
521 int ICollection.Count
|
|
522 {
|
|
523 get { return _list.Count; }
|
|
524 }
|
|
525
|
|
526 bool ICollection.IsSynchronized
|
|
527 {
|
|
528 get { return _list.IsSynchronized; }
|
|
529 }
|
|
530
|
|
531 object ICollection.SyncRoot
|
|
532 {
|
|
533 get { return _list.SyncRoot; }
|
|
534 }
|
|
535
|
|
536 #endregion
|
|
537
|
|
538 #region IEnumerable Members
|
|
539
|
|
540 IEnumerator IEnumerable.GetEnumerator()
|
|
541 {
|
|
542 return _list.GetEnumerator();
|
|
543 }
|
|
544
|
|
545 #endregion
|
|
546 }
|
|
547 }
|