1 /* System.Web.UI.HtmlControls
3 * Leen Toelen (toelen@hotmail.com)
9 using System
.Web
.UI
.WebControls
;
10 using System
.Web
.Util
;
11 using System
.Globalization
;
12 using System
.ComponentModel
;
13 using System
.Collections
;
14 using System
.Collections
.Specialized
;
16 namespace System
.Web
.UI
.HtmlControls
{
18 [ControlBuilder (typeof (HtmlSelectBuilder
))]
19 [DefaultEvent("ServerChange")]
20 [ValidationProperty("Value")]
21 public class HtmlSelect
: HtmlContainerControl
, IPostBackDataHandler
{
24 private int _cachedSelectedIndex
;
25 private object _dataSource
;
26 private static readonly object EventServerChange
= new object ();
27 private ListItemCollection _items
;
29 public HtmlSelect():base("select"){
30 _cachedSelectedIndex
= -1;
33 protected override void AddParsedSubObject(object obj
){
34 if (obj
as ListItem
!= null) {
35 this.Items
.Add((ListItem
) obj
);
38 throw new HttpException("HtmlSelect cannot have children of Type " + obj
.GetType().Name
);
41 protected virtual void ClearSelection()
43 foreach (ListItem item
in Items
)
44 item
.Selected
= false;
47 protected override ControlCollection
CreateControlCollection(){
48 return new EmptyControlCollection(this);
51 protected override void LoadViewState(object savedState
)
53 if (savedState
!= null) {
54 Triplet state
= (Triplet
) savedState
;
55 base.LoadViewState (state
.First
);
56 Items
.LoadViewState (state
.Second
);
57 object indices
= state
.Third
;
58 if (indices
!= null) {
59 Select ((int []) indices
);
64 protected override void OnDataBinding (EventArgs e
)
66 base.OnDataBinding (e
);
67 IEnumerable resolvedDataSource
= DataSourceHelper
.GetResolvedDataSource (DataSource
, DataMember
);
68 if (resolvedDataSource
!= null) {
69 string text
= DataTextField
;
70 string value = DataValueField
;
73 ICollection rdsCollection
= resolvedDataSource
as ICollection
;
74 if (rdsCollection
!= null)
75 Items
.Capacity
= rdsCollection
.Count
;
78 if (text
.Length
> 0 && value.Length
> 0)
81 foreach (object current
in resolvedDataSource
) {
82 ListItem li
= new ListItem ();
85 li
.Text
= DataBinder
.GetPropertyValue (current
, text
, null);
87 li
.Value
= DataBinder
.GetPropertyValue (current
, value, null);
89 li
.Value
= li
.Text
= current
.ToString();
96 if (_cachedSelectedIndex
!= -1) {
97 SelectedIndex
= _cachedSelectedIndex
;
98 _cachedSelectedIndex
= -1;
102 protected override void OnPreRender(EventArgs e
){
103 if (Page
!= null && Size
>= 0 && !Disabled
){
104 Page
.RegisterRequiresPostBack(this);
108 protected virtual void OnServerChange(EventArgs e
){
109 EventHandler handler
= (EventHandler
) Events
[EventServerChange
];
114 protected override void RenderAttributes(HtmlTextWriter writer
){
115 writer
.WriteAttribute("name", Name
);
116 Attributes
.Remove("name");
117 Attributes
.Remove("DataValueField");
118 Attributes
.Remove("DataTextField");
119 Attributes
.Remove("DataMember");
120 base.RenderAttributes(writer
);
123 protected override void RenderChildren(HtmlTextWriter writer
){
126 // increase indent level, improves readability
127 writer
.Indent
= writer
.Indent
+ 1;
128 if (Items
.Count
>= 0){
129 // display all options, and set the selected option
130 bool rendered_selected
= false;
131 foreach (ListItem option
in Items
){
132 //write begin tag with attributes
133 writer
.WriteBeginTag("option");
134 if (!rendered_selected
&& option
.Selected
){
135 writer
.WriteAttribute("selected","selected");
137 rendered_selected
= true;
139 else if (option
.Selected
){
140 option
.Selected
= false;
143 writer
.WriteAttribute("value",option
.Value
,true);
144 option
.Attributes
.Remove("text");
145 option
.Attributes
.Remove("value");
146 option
.Attributes
.Remove("selected");
147 option
.Attributes
.Render(writer
);
149 //write the option text
150 HttpUtility
.HtmlEncode(option
.Text
, writer
);
151 //close the current option tag
152 writer
.WriteEndTag("option");
157 // set the indent level back to normal
158 writer
.Indent
= writer
.Indent
- 1;
161 protected override object SaveViewState ()
163 object baseViewState
= base.SaveViewState ();
164 object itemsViewState
= Items
.SaveViewState ();
165 object indices
= null;
167 if (Events
[EventServerChange
] != null || !Disabled
|| Visible
)
168 indices
= SelectedIndices
;
170 if (indices
!= null || baseViewState
!= null || itemsViewState
!= null)
171 return new Triplet (baseViewState
, itemsViewState
, indices
);
176 protected virtual void Select(int[] selectedIndices
){
177 // unselect all options
179 // iterate through options, and set when selected
180 foreach (int current
in selectedIndices
){
181 if (current
>= 0 && current
< Items
.Count
){
182 Items
[current
].Selected
= true;
187 bool IPostBackDataHandler
.LoadPostData (string postDataKey
,
188 NameValueCollection postCollection
)
190 //get the posted selectedIndices[]
191 string [] postedValueColl
= postCollection
.GetValues(postDataKey
);
192 bool changed
= false;
193 if (postedValueColl
!= null){
196 //int postedValue = Items.FindIndexByValue(postedValueColl[0]);
197 int postedValue
= Items
.IndexOf(Items
.FindByValue(postedValueColl
[0]));
198 if (postedValue
!= SelectedIndex
){
199 //set the SelectedIndex
200 SelectedIndex
= postedValue
;
206 int postedValueCount
= postedValueColl
.Length
;
207 int[] arr
= new int[postedValueCount
];
208 //fill an array with the posted Values
209 for (int i
= 0; i
< postedValueCount
; i
++)
210 arr
[i
] = Items
.IndexOf(Items
.FindByValue(postedValueColl
[i
]));
211 //test if everything went fine
212 if( postedValueCount
== SelectedIndices
.Length
){
213 for (int i
= 0; i
< postedValueCount
; i
++)
214 if(arr
[i
] != SelectedIndices
[i
])
219 //commit the posted Values
224 else if (SelectedIndex
!= -1){
231 void IPostBackDataHandler
.RaisePostDataChangedEvent ()
233 OnServerChange (EventArgs
.Empty
);
236 //starts tracking changes to the viewstate
237 protected override void TrackViewState(){
238 base.TrackViewState();
239 Items
.TrackViewState();
242 [WebCategory("Action")]
243 [WebSysDescription("Fires when the selection changes.")]
244 public event EventHandler ServerChange
{
246 Events
.AddHandler(EventServerChange
, value);
249 Events
.RemoveHandler(EventServerChange
, value);
254 [WebCategory("Data")]
255 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
256 [WebSysDescription("The data member of the select.")]
257 public virtual string DataMember
{
259 object viewStateDataMember
= ViewState
["DataMember"];
260 if ( viewStateDataMember
!= null) return (String
) viewStateDataMember
;
264 Attributes
["DataMember"] = HtmlControl
.AttributeToString(value);
269 [WebCategory("Data")]
270 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
271 [WebSysDescription("The data source used to populate the list with data.")]
272 public virtual object DataSource
{
277 if (value != null && !(value is IListSource
)) {
278 if (!(value is IEnumerable
))
279 throw new ArgumentException ("Invalid dataSource type");
286 [WebCategory("Data")]
287 [WebSysDescription("The field in the data source that provides the item value.")]
288 public virtual string DataTextField
{
290 string attr
= Attributes
["DataTextField"];
297 Attributes
["DataTextField"] = AttributeToString(value);
302 [WebCategory("Data")]
303 [WebSysDescription("The field in the data source that provides the item value.")]
304 public virtual string DataValueField
{
306 string attr
= Attributes
["DataValueField"];
307 if (attr
!= null)return attr
;
311 Attributes
["DataValueField"] = AttributeToString(value);
315 public override string InnerHtml
{
317 throw new NotSupportedException("InnerHtml is not supported by " + this.GetType().Name
);
320 throw new NotSupportedException("InnerHtml is not supported by " + this.GetType().Name
);
324 public override string InnerText
{
326 throw new NotSupportedException("InnerText is not supported by " + this.GetType().Name
);
329 throw new NotSupportedException("InnerText is not supported by " + this.GetType().Name
);
334 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
335 public ListItemCollection Items
{
338 _items
= new ListItemCollection();
339 if (IsTrackingViewState
) _items
.TrackViewState();
346 [WebCategory("Behavior")]
347 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
348 public bool Multiple
{
350 string attr
= Attributes
["multiple"];
351 if (attr
!= null) return (0 == String
.Compare (attr
, "true", true));
355 Attributes
["multiple"] = value.ToString ();
360 [WebCategory("Behavior")]
361 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
372 [HtmlControlPersistable (false)]
374 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
375 public virtual int SelectedIndex
{
377 for (int i
=0; i
<Items
.Count
; i
++){
378 if (Items
[i
].Selected
== true) return i
;
380 if (Size
<=1 && !Multiple
){
381 if(Items
.Count
> 0) Items
[0].Selected
= true;
387 if(Items
.Count
== 0){
388 _cachedSelectedIndex
= value;
392 if (value < -1 || value >= Items
.Count
)
393 throw new ArgumentOutOfRangeException();
397 Items
[value].Selected
= true;
401 protected virtual int[] SelectedIndices
{
403 int[] indices
= new int[3];
404 int indicesCount
= 0;
405 for(int i
=0; i
< Items
.Count
; i
++){
406 if (Items
[i
].Selected
){
407 if( indicesCount
== (int) indices
.Length
){
408 int[] temp
= new int[indicesCount
+ indicesCount
];
409 indices
.CopyTo(temp
,0);
412 indices
[indicesCount
] = i
;
416 int[] arr
= new int[indicesCount
];
417 System
.Array
.Copy(indices
,0,arr
,0,indicesCount
);
422 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
425 string attr
= Attributes
["size"];
427 return Int32
.Parse(attr
, CultureInfo
.InvariantCulture
);
432 Attributes
["size"] = AttributeToString(value);
436 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
437 public string Value
{
439 int selectedIndex
= SelectedIndex
;
440 if (selectedIndex
>=0 && selectedIndex
< Items
.Count
){
441 return Items
[selectedIndex
].Value
;
446 int findValue
= Items
.IndexOf(Items
.FindByValue(value));
447 if (findValue
>= 0) SelectedIndex
= findValue
;
451 } // class HtmlSelect
452 } // namespace System.Web.UI.HtmlControls