2010-04-26 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListBindingHelper.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2007 Novell, Inc.
21 //
22 // Author:
23 //      Carlos Alberto Cortez <calberto.cortez@gmail.com>
24 //      Ivan Zlatev <contact@i-nz.net>
25 //
26
27 using System;
28 using System.Collections;
29 using System.ComponentModel;
30 using System.Reflection;
31
32 #if NET_2_0
33 using System.Collections.Generic;
34 #endif
35
36 namespace System.Windows.Forms
37 {
38
39 #if NET_2_0
40         public
41 #else
42         internal
43 #endif
44         static class ListBindingHelper 
45         {
46                 public static object GetList (object list)
47                 {
48                         if (list is IListSource)
49                                 return ((IListSource) list).GetList ();
50                         return list;
51                 }
52
53                 public static object GetList (object dataSource, string dataMember)
54                 {
55                         dataSource = GetList (dataSource);
56                         if (dataSource == null || dataMember == null || dataMember.Length == 0)
57                                 return dataSource;
58
59                         PropertyDescriptor property = GetListItemProperties (dataSource).Find (dataMember, true);
60                         if (property == null)
61                                 throw new ArgumentException ("dataMember");
62
63                         object item = null;
64 #if NET_2_0
65                         ICurrencyManagerProvider currencyManagerProvider = dataSource as ICurrencyManagerProvider;
66                         if (currencyManagerProvider != null && currencyManagerProvider.CurrencyManager != null) {
67                                 CurrencyManager currencyManager = currencyManagerProvider.CurrencyManager;
68                                 if (currencyManager != null && currencyManager.Count > 0 && currencyManager.Current != null)
69                                         item = currencyManager.Current;
70                         }
71 #endif
72
73                         if (item == null) {
74                                 if (dataSource is IEnumerable) {
75                                         if (dataSource is IList) {
76                                                 IList list = (IList) dataSource;
77                                                 item = list.Count > 0 ? list[0] : null;
78                                         } else {
79                                                 IEnumerator e = ((IEnumerable) dataSource).GetEnumerator ();
80                                                 if (e != null && e.MoveNext ())
81                                                         item = e.Current;
82                                         }
83                                 } else {
84                                         item = dataSource;
85                                 }
86                         }
87
88                         if (item != null)
89                                 return property.GetValue (item);
90                         return null;
91                 }
92
93                 public static Type GetListItemType (object list)
94                 {
95                         return GetListItemType (list, String.Empty);
96                 }
97
98                 public static Type GetListItemType (object dataSource, string dataMember)
99                 {
100                         if (dataSource == null)
101                                 return null;
102
103                         if (dataMember != null && dataMember.Length > 0) {
104                                 PropertyDescriptor property = GetProperty (dataSource, dataMember);
105                                 if (property == null)
106                                         return typeof (object);
107
108                                 return property.PropertyType;
109                         }
110
111                         if (dataSource is Array)
112                                 return dataSource.GetType ().GetElementType ();
113
114                         // IEnumerable seems to have higher precedence over IList
115                         if (dataSource is IEnumerable) {
116                                 IEnumerator enumerator = ((IEnumerable) dataSource).GetEnumerator ();
117                                 if (enumerator.MoveNext () && enumerator.Current != null)
118                                         return enumerator.Current.GetType ();
119
120                                 if (dataSource is IList
121 #if NET_2_0
122                                         || dataSource.GetType () == typeof (IList<>)
123 #endif
124                                         ) {
125                                         PropertyInfo property = GetPropertyByReflection (dataSource.GetType (), "Item");
126                                         if (property != null) // `Item' could be interface-explicit, and thus private
127                                                 return property.PropertyType;
128                                 }
129
130                                 // fallback to object
131                                 return typeof (object);
132                         }
133
134                         return dataSource.GetType ();
135                 }
136
137                 public static PropertyDescriptorCollection GetListItemProperties (object list)
138                 {
139                         return GetListItemProperties (list, null);
140                 }
141
142                 public static PropertyDescriptorCollection GetListItemProperties (object list, PropertyDescriptor [] listAccessors)
143                 {
144                         list = GetList (list);
145
146                         if (list == null)
147                                 return new PropertyDescriptorCollection (null);
148
149                         if (list is ITypedList)
150                                 return ((ITypedList)list).GetItemProperties (listAccessors);
151
152                         if (listAccessors == null || listAccessors.Length == 0) {
153                                 Type item_type = GetListItemType (list);
154                                 return TypeDescriptor.GetProperties (item_type, 
155                                         new Attribute [] { new BrowsableAttribute (true) });
156                         }
157
158                         // Take into account only the first property
159                         Type property_type = listAccessors [0].PropertyType;
160                         if (typeof (IList).IsAssignableFrom (property_type)
161 #if NET_2_0
162                                 || typeof (IList<>).IsAssignableFrom (property_type)
163 #endif
164                                 ) {
165
166                                 PropertyInfo property = GetPropertyByReflection (property_type, "Item");
167                                 return TypeDescriptor.GetProperties (property.PropertyType);
168                         }
169
170                         return new PropertyDescriptorCollection (new PropertyDescriptor [0]);
171                 }
172
173                 public static PropertyDescriptorCollection GetListItemProperties (object dataSource, string dataMember, 
174                         PropertyDescriptor [] listAccessors)
175                 {
176                         throw new NotImplementedException ();
177                 }
178
179                 public static string GetListName (object list, PropertyDescriptor [] listAccessors)
180                 {
181                         if (list == null)
182                                 return String.Empty;
183
184                         Type item_type = GetListItemType (list);
185                         return item_type.Name;
186                 }
187
188                 static PropertyDescriptor GetProperty (object obj, string property_name)
189                 {
190                         return TypeDescriptor.GetProperties (obj, 
191                                                              new Attribute [] { new BrowsableAttribute (true) })[property_name];
192                 }
193
194                 // 
195                 // Need to use reflection as we need to bypass the TypeDescriptor.GetProperties () limitations
196                 //
197                 static PropertyInfo GetPropertyByReflection (Type type, string property_name)
198                 {
199                         foreach (PropertyInfo prop in type.GetProperties (BindingFlags.Public | BindingFlags.Instance))
200                                 if (prop.Name == property_name)
201                                         return prop;
202
203                         return null;
204                 }
205         }
206 }