1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
31 using System
.Collections
;
32 using System
.ComponentModel
;
33 using System
.Reflection
;
35 namespace System
.Windows
.Forms
37 public abstract class ListControl
: Control
39 private object data_source
;
40 private BindingMemberInfo value_member
;
41 private string display_member
;
42 private CurrencyManager data_manager
;
44 private bool formatting_enabled
;
47 protected ListControl ()
50 value_member
= new BindingMemberInfo (string.Empty
);
51 display_member
= string.Empty
;
53 SetStyle (ControlStyles
.StandardClick
| ControlStyles
.UserPaint
55 | ControlStyles
.UseTextForAccessibility
61 static object DataSourceChangedEvent
= new object ();
62 static object DisplayMemberChangedEvent
= new object ();
63 static object SelectedValueChangedEvent
= new object ();
64 static object ValueMemberChangedEvent
= new object ();
66 public event EventHandler DataSourceChanged
{
67 add { Events.AddHandler (DataSourceChangedEvent, value); }
68 remove { Events.RemoveHandler (DataSourceChangedEvent, value); }
71 public event EventHandler DisplayMemberChanged
{
72 add { Events.AddHandler (DisplayMemberChangedEvent, value); }
73 remove { Events.RemoveHandler (DisplayMemberChangedEvent, value); }
76 public event EventHandler SelectedValueChanged
{
77 add { Events.AddHandler (SelectedValueChangedEvent, value); }
78 remove { Events.RemoveHandler (SelectedValueChangedEvent, value); }
81 public event EventHandler ValueMemberChanged
{
82 add { Events.AddHandler (ValueMemberChangedEvent, value); }
83 remove { Events.RemoveHandler (ValueMemberChangedEvent, value); }
88 #region .NET 2.0 Public Properties
90 public bool FormattingEnabled
{
91 get { return formatting_enabled; }
92 set { formatting_enabled = value; }
97 #region Public Properties
100 [RefreshProperties(RefreshProperties
.Repaint
)]
101 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts
.AssemblySystem_Design
)]
102 public object DataSource
{
103 get { return data_source; }
105 if (data_source
== value)
109 display_member
= String
.Empty
;
110 else if (!(value is IList
|| value is IListSource
))
111 throw new Exception ("Complex DataBinding accepts as a data source " +
112 "either an IList or an IListSource");
115 ConnectToDataSource ();
116 OnDataSourceChanged (EventArgs
.Empty
);
121 [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + Consts
.AssemblySystem_Design
, typeof(System
.Drawing
.Design
.UITypeEditor
))]
122 [TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, " + Consts
.AssemblySystem_Design
)]
123 public string DisplayMember
{
125 return display_member
;
129 value = String
.Empty
;
131 if (display_member
== value) {
135 display_member
= value;
136 ConnectToDataSource ();
137 OnDisplayMemberChanged (EventArgs
.Empty
);
141 public abstract int SelectedIndex
{
146 [Bindable(BindableSupport
.Yes
)]
149 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
150 public object SelectedValue
{
152 if (data_manager
== null) {
156 object item
= data_manager
[SelectedIndex
];
157 object fil
= FilterItemOnProperty (item
, ValueMember
);
164 if (value is string) {
165 string valueString
= value as string;
166 if (valueString
== String
.Empty
)
170 if (data_manager
!= null) {
172 PropertyDescriptorCollection col
= data_manager
.GetItemProperties ();
173 PropertyDescriptor prop
= col
.Find (ValueMember
, true);
175 for (int i
= 0; i
< data_manager
.Count
; i
++) {
176 if (prop
.GetValue (data_manager
[i
]) == value) {
187 [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + Consts
.AssemblySystem_Design
, typeof(System
.Drawing
.Design
.UITypeEditor
))]
188 public string ValueMember
{
189 get { return value_member.BindingMember; }
191 BindingMemberInfo new_value
= new BindingMemberInfo (value);
193 if (value_member
.Equals (new_value
)) {
197 value_member
= new_value
;
199 if (display_member
== string.Empty
) {
200 DisplayMember
= value_member
.BindingMember
;
203 ConnectToDataSource ();
204 OnValueMemberChanged (EventArgs
.Empty
);
208 #endregion Public Properties
210 #region Public Methods
212 protected object FilterItemOnProperty (object item
)
214 return FilterItemOnProperty (item
, string.Empty
);
217 protected object FilterItemOnProperty (object item
, string field
)
222 if (field
== null || field
== string.Empty
)
225 PropertyDescriptor prop
= null;
227 if (data_manager
!= null) {
228 PropertyDescriptorCollection col
= data_manager
.GetItemProperties ();
229 prop
= col
.Find (field
, true);
235 return prop
.GetValue (item
);
238 public string GetItemText (object item
)
240 if (data_manager
!= null) {
241 object fil
= FilterItemOnProperty (item
, DisplayMember
);
243 return fil
.ToString ();
247 return item
.ToString ();
250 protected CurrencyManager DataManager
{
251 get { return data_manager; }
254 // Used only by ListBox to avoid to break Listbox's member signature
255 protected override bool IsInputKey (Keys keyData
)
266 case Keys
.ControlKey
:
276 protected override void OnBindingContextChanged (EventArgs e
)
278 base.OnBindingContextChanged (e
);
279 ConnectToDataSource ();
281 if (DataManager
!= null) {
282 SetItemsCore (DataManager
.List
);
283 SelectedIndex
= DataManager
.Position
;
287 protected virtual void OnDataSourceChanged (EventArgs e
)
289 EventHandler eh
= (EventHandler
)(Events
[DataSourceChangedEvent
]);
294 protected virtual void OnDisplayMemberChanged (EventArgs e
)
296 EventHandler eh
= (EventHandler
)(Events
[DisplayMemberChangedEvent
]);
301 protected virtual void OnSelectedIndexChanged (EventArgs e
)
303 if (data_manager
== null)
305 if (data_manager
.Position
== SelectedIndex
)
307 data_manager
.Position
= SelectedIndex
;
310 protected virtual void OnSelectedValueChanged (EventArgs e
)
312 EventHandler eh
= (EventHandler
)(Events
[SelectedValueChangedEvent
]);
317 protected virtual void OnValueMemberChanged (EventArgs e
)
319 EventHandler eh
= (EventHandler
)(Events
[ValueMemberChangedEvent
]);
324 protected abstract void RefreshItem (int index
);
326 protected virtual void SetItemCore (int index
, object value)
331 protected abstract void SetItemsCore (IList items
);
333 #endregion Public Methods
335 #region Private Methods
337 internal void BindDataItems ()
339 if (data_manager
!= null) {
340 SetItemsCore (data_manager
.List
);
344 private void ConnectToDataSource ()
346 if (data_source
== null) {
351 if (BindingContext
== null) {
355 data_manager
= (CurrencyManager
) BindingContext
[data_source
];
356 data_manager
.PositionChanged
+= new EventHandler (OnPositionChanged
);
357 data_manager
.ItemChanged
+= new ItemChangedEventHandler (OnItemChanged
);
360 private void OnItemChanged (object sender
, ItemChangedEventArgs e
)
362 /* if the list has changed, tell our subclass to re-bind */
364 SetItemsCore (data_manager
.List
);
366 RefreshItem (e
.Index
);
369 private void OnPositionChanged (object sender
, EventArgs e
)
371 SelectedIndex
= data_manager
.Position
;
374 #endregion Private Methods