d2571e6205c065982ce15cdee32085d22fe4c829
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / ListControl.cs
1 //
2 // System.Web.UI.WebControls.ListControl.cs
3 //
4 // Authors:
5 //   Gaurav Vaish (gvaish@iitk.ac.in)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) Gaurav Vaish (2002)
9 // (C) 2003 Andreas Nahr
10 //
11 \r
12 using System;\r
13 using System.Collections;\r
14 using System.ComponentModel;
15 using System.ComponentModel.Design;\r
16 using System.Web;\r
17 using System.Web.UI;\r
18 using System.Web.Util;\r
19 \r
20 namespace System.Web.UI.WebControls\r
21 {\r
22         [DefaultEvent("SelectedIndexChanged")]\r
23         #if !NET_1_2
24         [DefaultProperty("DataSource")]
25         #endif\r
26         [Designer ("System.Web.UI.Design.WebControls.ListControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]\r
27         [DataBindingHandler("System.Web.UI.Design.ListControlDataBindingHandler, " + Consts.AssemblySystem_Design)]\r
28         [ParseChildren(true, "Items")]\r
29         public abstract class ListControl : 
30                 #if NET_1_2
31                         DataBoundControl
32                 #else
33                         WebControl
34                 #endif\r
35         {\r
36                 private static readonly object SelectedIndexChangedEvent = new object();\r
37
38                 #if !NET_1_2\r
39                 private object             dataSource;
40                 #endif
41                 \r
42                 private ListItemCollection items;\r
43 \r
44                 private int cachedSelectedIndex = -1;\r
45                 private string cachedSelectedValue;
46
47                 #if !NET_1_2\r
48                 public ListControl(): base(HtmlTextWriterTag.Select)\r
49                 {\r
50                 }
51                 #else
52                 protected override HtmlTextWriterTag TagKey {
53                         get { return HtmlTextWriterTag.Select; }
54                 }
55                 #endif\r
56
57                 [WebCategory ("Action")]
58                 [WebSysDescription ("Raised when the selected index entry has changed.")]\r
59                 public event EventHandler SelectedIndexChanged\r
60                 {\r
61                         add\r
62                         {\r
63                                 Events.AddHandler(SelectedIndexChangedEvent, value);\r
64                         }\r
65                         remove\r
66                         {\r
67                                 Events.RemoveHandler(SelectedIndexChangedEvent, value);\r
68                         }\r
69                 }\r
70
71                 [DefaultValue (false), WebCategory ("Behavior")]
72                 [WebSysDescription ("The control automatically posts back after changing the text.")]\r
73                 public virtual bool AutoPostBack\r
74                 {\r
75                         get\r
76                         {\r
77                                 object o = ViewState["AutoPostBack"];\r
78                                 if(o!=null)\r
79                                         return (bool)o;\r
80                                 return false;\r
81                         }\r
82                         set\r
83                         {\r
84                                 ViewState["AutoPostBack"] = value;\r
85                         }\r
86                 }\r
87
88                 #if !NET_1_2
89                 [DefaultValue (""), WebCategory ("Data")]
90                 [WebSysDescription ("The name of the table that is used for binding when a DataSource is specified.")]\r
91                 public virtual string DataMember\r
92                 {\r
93                         get\r
94                         {\r
95                                 object o = ViewState["DataMember"];\r
96                                 if(o!=null)\r
97                                         return (string)o;\r
98                                 return String.Empty;\r
99                         }\r
100                         set\r
101                         {\r
102                                 ViewState["DataMember"] = value;\r
103                         }\r
104                 }\r
105
106
107                 [DefaultValue (null), Bindable (true), WebCategory ("Data")]
108                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
109                 [WebSysDescription ("The DataSource that is used for data-binding.")]\r
110                 public virtual object DataSource\r
111                 {\r
112                         get\r
113                         {\r
114                                 return dataSource;\r
115                         }\r
116                         set\r
117                         {\r
118                                 if(value == null || value is IListSource || value is IEnumerable) {
119                                         dataSource = value;
120                                         return;
121                                 }
122                                 throw new ArgumentException(HttpRuntime.FormatResourceString(ID, "Invalid DataSource Type"));\r
123                         }\r
124                 }
125                 #endif\r
126
127                 [DefaultValue (""), WebCategory ("Data")]
128                 [WebSysDescription ("The field in the datatable that provides the text entry.")]\r
129                 public virtual string DataTextField\r
130                 {\r
131                         get\r
132                         {\r
133                                 object o = ViewState["DataTextField"];\r
134                                 if(o!=null)\r
135                                         return (string)o;\r
136                                 return String.Empty;\r
137                         }\r
138                         set\r
139                         {\r
140                                 ViewState["DataTextField"] = value;\r
141                         }\r
142                 }\r
143
144                 [DefaultValue (""), WebCategory ("Data")]
145                 [WebSysDescription ("Specifies a formatting rule for the texts that are returned.")]\r
146                 public virtual string DataTextFormatString\r
147                 {\r
148                         get\r
149                         {\r
150                                 object o = ViewState["DataTextFormatString"];\r
151                                 if(o!=null)\r
152                                         return (string)o;\r
153                                 return String.Empty;\r
154                         }\r
155                         set\r
156                         {\r
157                                 ViewState["DataTextFormatString"] = value;\r
158                         }\r
159                 }\r
160
161                 [DefaultValue (""), WebCategory ("Data")]
162                 [WebSysDescription ("The field in the datatable that provides the entry value.")]\r
163                 public virtual string DataValueField\r
164                 {\r
165                         get\r
166                         {\r
167                                 object o = ViewState["DataValueField"];\r
168                                 if(o!=null)\r
169                                         return (string)o;\r
170                                 return String.Empty;\r
171                         }\r
172                         set\r
173                         {\r
174                                 ViewState["DataValueField"] = value;\r
175                         }\r
176                 }\r
177
178                 [DefaultValue (null), MergableProperty (false), WebCategory ("Misc")]
179                 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
180                 [WebSysDescription ("A collection of all items contained in this list.")]\r
181                 public virtual ListItemCollection Items\r
182                 {\r
183                         get\r
184                         {\r
185                                 if(items==null)\r
186                                 {\r
187                                         items = new ListItemCollection();\r
188                                         if(IsTrackingViewState)\r
189                                         {\r
190                                                 items.TrackViewState();\r
191                                         }\r
192                                 }\r
193                                 return items;\r
194                         }\r
195                 }\r
196
197                 [DefaultValue (0), Bindable (true), WebCategory ("Misc")]
198                 [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
199                 [WebSysDescription ("The index number of the currently selected ListItem.")]\r
200                 public virtual int SelectedIndex\r
201                 {\r
202                         get {\r
203                                 ListItemCollection items = Items;\r
204                                 int last = items.Count;\r
205                                 for (int i = 0; i < last; i++) {\r
206                                         if (items [i].Selected)\r
207                                                 return i;\r
208                                 }\r
209                                 return -1;\r
210                         }\r
211                         set {\r
212                                 if (value < -1 || value > Items.Count)\r
213                                         throw new ArgumentOutOfRangeException ();\r
214 \r
215                                 ClearSelection ();\r
216                                 if (value != -1)\r
217                                         Items [value].Selected = true;\r
218                         }\r
219                 }\r
220
221                 [DefaultValue (null), WebCategory ("Misc")]
222                 [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
223                 [WebSysDescription ("The currently selected ListItem.")]\r
224                 public virtual ListItem SelectedItem\r
225                 {\r
226                         get\r
227                         {\r
228                                 int idx = SelectedIndex;\r
229                                 if (idx < 0)\r
230                                         return null;\r
231 \r
232                                 return Items [idx];\r
233                         }\r
234                 }\r
235 \r
236 #if NET_1_1
237                 [DefaultValue (""), Bindable (true), WebCategory ("Misc")]
238                 [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
239                 [WebSysDescription ("The value of the currently selected ListItem.")]\r
240                 public virtual string SelectedValue {\r
241                         get {\r
242                                 int idx = SelectedIndex;\r
243                                 if (idx == -1)\r
244                                         return "";\r
245 \r
246                                 return Items [idx].Value;\r
247                         }\r
248 \r
249                         set {\r
250                                 ListItem item = null;\r
251 \r
252                                 if (value != null) {\r
253                                         if (Items.Count > 0) {
254                                                 item = Items.FindByValue (value);
255                                                 if (item == null)
256                                                         throw new ArgumentOutOfRangeException ("value");
257                                         } else {
258                                                 cachedSelectedValue = value;
259                                                 return;
260                                         }
261                                 }\r
262 \r
263                                 ClearSelection ();\r
264                                 if (item != null)\r
265                                         item.Selected = true;\r
266                         }\r
267                 }\r
268 #endif\r
269                 \r
270                 internal virtual ArrayList SelectedIndices\r
271                 {\r
272                         get\r
273                         {\r
274                                 ArrayList si = new ArrayList();\r
275                                 for(int i=0; i < Items.Count; i++)\r
276                                 {\r
277                                         if(Items[i].Selected)\r
278                                                 si.Add(i);\r
279                                 }\r
280                                 return si;\r
281                         }\r
282                 }\r
283 \r
284                 internal void Select(ArrayList indices)\r
285                 {\r
286                         ClearSelection();\r
287                         foreach(object intObj in indices)\r
288                         {\r
289                                 int index = (int)intObj;\r
290                                 if(index >= 0 && index < Items.Count)\r
291                                         Items[index].Selected = true;\r
292                         }\r
293                 }\r
294 \r
295                 public virtual void ClearSelection()\r
296                 {\r
297                         for(int i=0; i < Items.Count; i++)\r
298                         {\r
299                                 Items[i].Selected = false;\r
300                         }\r
301                 }\r
302 \r
303                 protected override void LoadViewState(object savedState)\r
304                 {\r
305                         //Order: BaseClass, Items (Collection), Indices\r
306                         if(savedState != null && savedState is Triplet)\r
307                         {\r
308                                 Triplet state = (Triplet)savedState;\r
309                                 base.LoadViewState(state.First);\r
310                                 Items.LoadViewState(state.Second);\r
311                                 object indices = state.Third;\r
312                                 if(indices != null)\r
313                                 {\r
314                                         Select((ArrayList)indices);\r
315                                 }\r
316                         }\r
317                 }\r
318
319                 #if NET_1_2
320                 protected override void PerformDataBinding ()
321                 {
322                         base.PerformDataBinding ();
323                         IEnumerable ds = GetResolvedDataSource ();
324                 #else\r
325                 protected override void OnDataBinding(EventArgs e)\r
326                 {\r
327                         base.OnDataBinding(e);\r
328                         IEnumerable ds = DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
329                 #endif\r
330                         if(ds != null) {\r
331                                 string dtf = DataTextField;\r
332                                 string dvf = DataValueField;\r
333                                 string dtfs = DataTextFormatString;\r
334                                 if (dtfs.Length == 0)\r
335                                         dtfs = "{0}";\r
336 \r
337                                 Items.Clear();\r
338 \r
339                                 bool dontUseProperties = (dtf.Length == 0 && dvf.Length == 0);\r
340 \r
341                                 foreach (object current in ds) {\r
342                                         ListItem li = new ListItem();\r
343                                         if (dontUseProperties){\r
344                                                 li.Text  = String.Format (dtfs, current);\r
345                                                 li.Value = current.ToString ();\r
346                                                 Items.Add (li);\r
347                                                 continue;\r
348                                         }\r
349 \r
350                                         object o;\r
351                                         if (dtf.Length > 0) {\r
352                                                 o = DataBinder.GetPropertyValue (current, dtf, dtfs);\r
353                                                 li.Text = o.ToString ();\r
354                                         }\r
355 \r
356                                         if (dvf.Length > 0) {\r
357                                                 o = DataBinder.GetPropertyValue (current, dvf, null);\r
358                                                 li.Value = o.ToString ();\r
359                                         }\r
360 \r
361                                         Items.Add(li);\r
362                                 }\r
363                         }\r
364
365                         if (cachedSelectedValue != null) {
366                                 int index = Items.FindByValueInternal (cachedSelectedValue);
367                                 if (index == -1)
368                                         throw new ArgumentOutOfRangeException("value");
369
370                                 if (cachedSelectedIndex != -1 && cachedSelectedIndex != index)
371                                         throw new ArgumentException(HttpRuntime.FormatResourceString(
372                                                 "Attributes_mutually_exclusive", "Selected Index", "Selected Value"));
373
374                                 SelectedIndex = index;
375                                 cachedSelectedIndex = -1;
376                                 cachedSelectedValue = null;
377                                 return;
378                         }
379
380                         if (cachedSelectedIndex != -1) {\r
381                                 SelectedIndex = cachedSelectedIndex;\r
382                                 cachedSelectedIndex = -1;\r
383                         }\r
384                 }\r
385 \r
386                 protected virtual void OnSelectedIndexChanged(EventArgs e)\r
387                 {\r
388                         if(Events!=null)\r
389                                 {\r
390                                         EventHandler eh = (EventHandler)(Events[SelectedIndexChangedEvent]);\r
391                                         if(eh!=null)\r
392                                                 eh(this, e);\r
393                                 }\r
394                 }\r
395 \r
396                 protected override void OnPreRender (EventArgs e)\r
397                 {\r
398                         base.OnPreRender(e);\r
399                 }\r
400 \r
401                 protected override object SaveViewState()\r
402                 {\r
403                         //Order: BaseClass, Items (Collection), Indices\r
404                         object vs = base.SaveViewState();\r
405                         object itemSvs = Items.SaveViewState();\r
406                         object indices = null;\r
407                         if (SaveSelectedIndicesViewState)\r
408                                 indices = SelectedIndices;\r
409 \r
410                         if (vs != null || itemSvs != null || indices != null)\r
411                                 return new Triplet(vs, itemSvs, indices);\r
412 \r
413                         return null;\r
414                 }\r
415 \r
416                 protected override void TrackViewState()\r
417                 {\r
418                         base.TrackViewState();\r
419                         Items.TrackViewState();\r
420                 }\r
421 \r
422                 private bool SaveSelectedIndicesViewState {\r
423                         get {\r
424                                 if (Events[SelectedIndexChangedEvent] == null && Enabled && Visible) {\r
425                                         Type t = GetType();\r
426                                         // If I am a derivative, let it take of storing the selected indices.\r
427                                         if (t == typeof(DropDownList) || t == typeof(ListBox) ||\r
428                                             t == typeof(CheckBoxList) || t == typeof(RadioButtonList))\r
429                                                 return false;\r
430                                 }\r
431                                 return true;\r
432                         }\r
433                 }\r
434         }\r
435 }\r