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