File: UI\MobileControls\Adapters\WmlSelectionListAdapter.cs
Project: ndp\fx\src\mit\System\Web\System.Web.Mobile.csproj (System.Web.Mobile)
//------------------------------------------------------------------------------
// <copyright file="WmlSelectionListAdapter.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
using System;
using System.Globalization;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.MobileControls;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Collections;
using System.Text;
using System.Diagnostics;
using System.Security.Permissions;
 
#if COMPILING_FOR_SHIPPED_SOURCE
namespace System.Web.UI.MobileControls.ShippedAdapterSource
#else
namespace System.Web.UI.MobileControls.Adapters
#endif    
 
{
 
    /*
     * WmlSelectionListAdapter provides the wml device functionality for SelectionList controls.
     *
     * Copyright (c) 2000 Microsoft Corporation
     */
    /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter"]/*' />
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
    public class WmlSelectionListAdapter : WmlControlAdapter
    {
        private String _ivalue = null;
        private const String ClientPrefix = "__slst_";
 
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.Control"]/*' />
        protected new SelectionList Control
        {
            get
            {
                return (SelectionList)base.Control;
            }
        }
 
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.OnInit"]/*' />
        public override void OnInit(EventArgs e)
        {
        }
 
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.OnPreRender"]/*' />
        public override void OnPreRender(EventArgs e)
        {
            int firstSelectedIndex;
            MobileListItemCollection items = Control.Items;
            int count = items.Count;
            for(firstSelectedIndex = 0; firstSelectedIndex < count; firstSelectedIndex++)
            {
                if(items[firstSelectedIndex].Selected)
                {
                    break;
                }
            }
            if(firstSelectedIndex < count)
            {
                StringBuilder ivalue=new StringBuilder();
                ivalue.Append((firstSelectedIndex + 1).ToString(CultureInfo.InvariantCulture));
                if(Control.IsMultiSelect) 
                {
                    for(int i = firstSelectedIndex + 1; i < count; i++)
                    {
                        if(items[i].Selected)
                        {
                            ivalue.Append(";");
                            ivalue.Append((i + 1).ToString(CultureInfo.InvariantCulture));
                        }
                    }
                }
 
                _ivalue = ivalue.ToString();
            }
            else
            {
                String defaultValue = null;
 
                if (!Control.IsMultiSelect)
                {
                    // 1 is the first index of a single selection list
                    defaultValue = "1";
                }
                else if (Device.CanRenderSetvarZeroWithMultiSelectionList)
                {
                    // 0 means no items have been selected, for MultiSelect case
                    defaultValue = "0";
                }
 
                if (defaultValue != null)
                {
                    _ivalue = defaultValue;
                }
            }            
        }
 
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.Render"]/*' />
        public override void Render(WmlMobileTextWriter writer)
        {
            MobileListItemCollection items = Control.Items;
            int count = items.Count;
            if (count == 0)
            {
                return;
            }           
 
            writer.EnterLayout(Style);
            bool crossPagePost = !String.IsNullOrEmpty(Control.Form.Action);
 
            if (crossPagePost)
            {
                if (_ivalue != null)
                {
                    String formVariable = ClientPrefix + Control.ClientID;
                    writer.AddFormVariable (formVariable, _ivalue, false);
                    // does not render _ivalue if null or form variables written.
                    writer.RenderBeginSelect(Control.ClientID, formVariable, _ivalue, Control.Title, Control.IsMultiSelect);
                }
                else // _ivalue == null
                {
                    writer.RenderBeginSelect(Control.ClientID, null, null, Control.Title, Control.IsMultiSelect);
                }
            }
            else // !crossPagePost
            {
                if (_ivalue != null)
                {
                    writer.AddFormVariable (Control.ClientID, _ivalue, false);
                }
                // does not render _ivalue if null or form variables written.
                writer.RenderBeginSelect(null, Control.ClientID, _ivalue, Control.Title, Control.IsMultiSelect);            
            }
 
            foreach (MobileListItem item in items)
            {
                if (crossPagePost)
                {
                    writer.RenderSelectOption(item.Text, item.Value);
                }
                else
                {
                    writer.RenderSelectOption(item.Text);
                }
            }
            writer.RenderEndSelect(Control.BreakAfter);
            writer.ExitLayout(Style);
        }
 
        // Parse the WML posted data appropriately.
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.LoadPostData"]/*' />
        public override bool LoadPostData(String key,
                                          NameValueCollection data,
                                          Object controlPrivateData,
                                          out bool dataChanged)
        {
            int[] selectedItemIndices;
            String[] selectedItems = data.GetValues(key);
            Debug.Assert (String.IsNullOrEmpty(Control.Form.Action), 
                "Cross page post (!IsPostBack) assumed when Form.Action nonempty." +
                "LoadPostData should not have been be called.");
            // Note: controlPrivateData is selectedIndices from viewstate.
            int[] originalSelectedIndices = (int[])controlPrivateData;
 
            dataChanged = false;
 
            if (selectedItems == null)
            {
                // This shouldn't happen if we're posting back from the form that
                // contains the selection list. It could happen when being called 
                // as the result of a postback from another form on the page,
                // so we just return quietly.
 
                return true;
            }
 
            if (Control.Items.Count == 0)
            {
                return true;
            }
 
            // If singleselect && nothing was selected, select
            // first elt.  (Non-mobile DropDown does same by getting SelectedIndex).
            if(!Control.IsMultiSelect &&
               originalSelectedIndices.Length == 0 && 
               Control.Items.Count > 0)
            {
                Control.Items[0].Selected = true;
                originalSelectedIndices = new int[]{0};
            }
 
            
            // Case where nothing is selected.
            if(selectedItems == null ||
                (selectedItems.Length == 1 && 
                    (selectedItems[0] != null && selectedItems[0].Length == 0)) ||
                (selectedItems.Length == 1 && 
                    selectedItems[0] == "0"))  // non-selected MultiSelect case
            {
                selectedItems = new String[]{};
            }
 
            // WML multiselect case with more than one selection.
            if(selectedItems.Length == 1 && selectedItems[0].IndexOf(';') > -1)
            {
                String selected = selectedItems[0];
                // Eliminate trailing semicolon, if there is one.
                selected = Regex.Replace(selected, ";$", "");
                selectedItems = Regex.Split(selected, ";");
            }
 
            selectedItemIndices = new int[selectedItems.Length];
            for(int i = 0; i < selectedItems.Length; i++)
            {
                // WML iname gives index + 1, so subtract one back out. 
                selectedItemIndices[i] = Int32.Parse(selectedItems[i], CultureInfo.InvariantCulture) - 1;
            }
 
            // Do not assume posted selected indices are ascending.  
            // We do know originalSelectedIndices are ascending.
            Array.Sort(selectedItemIndices);
 
            // Check whether selections have changed.
            if(selectedItemIndices.Length != originalSelectedIndices.Length)
            {
                dataChanged = true;
            }
            else
            {
                for(int i = 0; i < selectedItemIndices.Length; i++)
                {
                    if(selectedItemIndices[i] != originalSelectedIndices[i])
                    {
                        dataChanged = true;
                    }
                }
            }
            
            for (int i = 0; i < Control.Items.Count; i++)
            {
                Control.Items[i].Selected = false;
            }
 
            for(int i = 0; i < selectedItemIndices.Length; i++)
            {
                Control.Items[selectedItemIndices[i]].Selected = true;
            }
            
            return true;
        }
 
        /// <include file='doc\WmlSelectionListAdapter.uex' path='docs/doc[@for="WmlSelectionListAdapter.GetPostBackValue"]/*' />
        protected override String GetPostBackValue()
        {
            // Optimization - if viewstate is enabled for this control, and the
            // postback returns to this page, we just let it do the trick.
 
            if (Control.Form.Action.Length > 0 || !IsViewStateEnabled())
            {
                return _ivalue != null ? _ivalue : String.Empty;
            }
            else
            {
                return null;
            }
        }
 
        private bool IsViewStateEnabled()
        {
            Control ctl = Control;
            while (ctl != null)
            {
                if (!ctl.EnableViewState)
                {
                    return false;
                }
                ctl = ctl.Parent;
            }
            return true;
        }
 
 
    }
 
}