public void AddOptionTag(HtmlOptionTag tag)
 {
     _options.Add(tag.Key, tag);
 }
        private void Insert(int index, string key, HtmlOptionTag value)
        {
            if (count == keys.Length)
                EnsureCapacity(count + 1);

            if (index < count)
            {
                Array.Copy(keys, index, keys, index + 1, count - index);
                Array.Copy(values, index, values, index + 1, count - index);
            }

            keys[index] = key;
            values[index] = value;
            count++;
            version++;
        }
        /// <summary>
        /// Creates a HtmlSelectTag from a HTMLSelectElementClass.
        /// </summary>
        /// <param name="selectElement"> The HTMLSelectElementClass to convert.</param>
        /// <returns> A HtmlSelectTag</returns>
        private HtmlSelectTag CreateHtmlSelectTag(HTMLSelectElementClass selectElement)
        {
            HtmlSelectTag tag = new HtmlSelectTag();

            tag.Class = selectElement.className;
            tag.Id = selectElement.id;
            if ( selectElement.name != null )
            {
                tag.Name = selectElement.name;
            }
            else
            {
                if ( selectElement.id != null )
                {
                    tag.Name = selectElement.id;
                }
                else
                {
                    tag.Name = selectElement.uniqueID;
                    tag.Id = selectElement.uniqueID;
                }
            }
            // TODO: parse from innerHtml
            // tag.OnClick =
            // tag.Style=currentNode.GetAttribute("style",currentNode.NamespaceURI);
            tag.Title = selectElement.title;

            if ( selectElement.multiple )
            {
                tag.Multiple=true;
            }

            tag.Value = selectElement.value;

            // tag.Options = new HtmlOptionCollection();
            //object noll = null;

            IHTMLElementCollection options = (IHTMLElementCollection)selectElement.children;

            // while ( options.MoveNext() )
            foreach ( object obj in options )
            {
                if ( obj is HTMLOptionElementClass )
                {
                    HTMLOptionElementClass option = (HTMLOptionElementClass)obj;

                    HtmlOptionTag optionTag = new HtmlOptionTag();
                    optionTag.Id = option.id;
                    if ( option.selected )
                    {
                        optionTag.Selected=true;
                    }

                    if ( option.text == null )
                    {
                        optionTag.Text = string.Empty;
                    }
                    else
                    {
                        optionTag.Text = option.text;
                    }

                    if ( option.value == null )
                    {
                        optionTag.Value = string.Empty;
                    }
                    else
                    {
                        optionTag.Value = option.value;
                    }

                    optionTag.Key = "Option " + tag.Options.Length.ToString();
                    tag.AddOptionTag(optionTag);
                }
            }

            return tag;
        }
        /// <summary>
        ///		Removes the element at the specified index of the <b>HtmlOptionCollection</b>.
        /// </summary>
        /// <param name="index">The zero-based index of the element to remove.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///		<paramref name="index"/> is outside the range of valid indices for the <see cref="HtmlOptionCollection"/>.
        ///	</exception>
        /// <exception cref="NotSupportedException">
        ///		<para>The <see cref="HtmlOptionCollection"/> is read-only.</para>
        ///		<para>-or-</para>
        ///		<para>The <b>HtmlOptionCollection</b> has a fixed size.</para>
        /// </exception>
        /// <remarks>
        ///		<para>The index sequence is based on the sort sequence. When an element is added, 
        ///		it is inserted into <see cref="HtmlOptionCollection"/> in the correct sort order, and 
        ///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
        ///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
        ///		elements are added or removed from the <see cref="HtmlOptionCollection"/>.</para>
        ///		<para>In collections of contiguous elements, such as lists, the elements that
        ///		follow the removed element move up to occupy the vacated spot. If the collection is
        ///		indexed, the indices of the elements that are moved are also updated.</para>
        /// </remarks>
        public virtual void RemoveAt(int index)
        {
            if (index < 0 || index >= count)
                throw new ArgumentOutOfRangeException("index", index, "The index is outside the range of valid indices.");

            count--;
            if (index < count)
            {
                Array.Copy(keys, index + 1, keys, index, count - index);
                Array.Copy(values, index + 1, values, index, count - index);
            }

            // We can't set the deleted entries equal to null, because they might be value types.
            // Instead, we'll create empty single-element arrays of the right type and copy them
            // over the entries we want to erase.
            string[] tempKey = new string[1];
            HtmlOptionTag[] tempVal = new HtmlOptionTag[1];
            Array.Copy(tempKey, 0, keys, count, 1);
            Array.Copy(tempVal, 0, values, count, 1);

            version++;
        }
        /// <summary>
        ///		Replaces the value at a specific index in the <b>HtmlOptionCollection</b>.
        /// </summary>
        /// <param name="index">The zero-based index at which to save <paramref name="value"/>.</param>
        /// <param name="value">The <see cref="HtmlOptionTag"/> to save into the <see cref="HtmlOptionCollection"/>.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///		<paramref name="index"/> is outside the range of valid indices for the <see cref="HtmlOptionCollection"/>.
        /// </exception>
        /// <remarks>
        ///		<para>The index sequence is based on the sort sequence. When an element is added, 
        ///		it is inserted into <see cref="HtmlOptionCollection"/> in the correct sort order, and 
        ///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
        ///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
        ///		elements are added or removed from the <see cref="HtmlOptionCollection"/>.</para>
        /// </remarks>
        public virtual void SetByIndex(int index, HtmlOptionTag value)
        {
            if (index < 0 || index >= count)
                throw new ArgumentOutOfRangeException("index", index, "The index is outside the range of valid indices.");

            values[index] = value;
            version++;
        }
 /// <summary>
 ///		Determines whether the <b>HtmlOptionCollection</b> contains a specific value.
 /// </summary>
 /// <param name="value">The value to locate in the <see cref="HtmlOptionCollection"/>.</param>
 /// <returns>
 ///		<b>true</b> if the <see cref="HtmlOptionCollection"/> contains an element with the specified 
 ///		<paramref name="value"/>; otherwise, <b>false</b>.
 /// </returns>
 public virtual bool ContainsValue(HtmlOptionTag value)
 {
     return (IndexOfValue(value) >= 0);
 }
 /// <summary>
 ///		Returns the zero-based index of the first occurrence of the specified value in
 ///		the <b>HtmlOptionCollection</b>.
 /// </summary>
 /// <param name="value">The value to locate in the <see cref="HtmlOptionCollection"/>.</param>
 /// <returns>
 ///		The zero-based index of <paramref name="value"/>, if <paramref name="value"/> is found in
 ///		the <see cref="HtmlOptionCollection"/>; otherwise, -1.
 /// </returns>
 /// <remarks>
 ///		<para>The index sequence is based on the sort sequence. When an element is added, 
 ///		it is inserted into <see cref="HtmlOptionCollection"/> in the correct sort order, and 
 ///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
 ///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
 ///		elements are added or removed from the <see cref="HtmlOptionCollection"/>.</para>
 ///		<para>The values of the elements of the <see cref="HtmlOptionCollection"/> are compared to the 
 ///		specified value using the Equals method.</para>
 ///		<para>This method uses a linear search; therefore, the average execution time is 
 ///		proportional to <see cref="HtmlOptionCollection.Count"/>.</para>
 /// </remarks>
 public virtual int IndexOfValue(HtmlOptionTag value)
 {
     return Array.IndexOf(values, value, 0, count);
 }
 public virtual int IndexOf(HtmlOptionTag value)
 {
     return list.IndexOfValue(value);
 }
        /// <summary>
        ///		Adds an element with the specified key and value to the <b>HtmlOptionCollection</b>.
        /// </summary>
        /// <param name="key">The key of the element to add.</param>
        /// <param name="value">The value of the element to add.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="key"/> is a null reference.</exception>
        /// <exception cref="ArgumentException">
        ///		<para>An element with the specified <paramref name="key"/> already exists in the <see cref="HtmlOptionCollection"/>.</para>
        ///		<para>-or-</para>
        ///		<para>The <b>HtmlOptionCollection</b> is set to use the <see cref="IComparable"/> interface,
        ///		and <paramref name="key"/> does not implement the <b>IComparable</b> interface.</para>
        /// </exception>
        /// <exception cref="InvalidOperationException">The comparer throws an exception.</exception>
        /// <exception cref="NotSupportedException">
        ///		<para>The <see cref="HtmlOptionCollection"/> is read-only.</para>
        ///		<para>-or-</para>
        ///		<para>The <b>HtmlOptionCollection</b> has a fixed size.</para>
        /// </exception>
        public virtual void Add(string key, HtmlOptionTag value)
        {
            if (Object.ReferenceEquals(key, null)) // avoids compiler error for null check on value type
                throw new ArgumentNullException("key", "The key cannot be null.");

            int index = Array.BinarySearch(keys, 0, count, key, comparer);

            if (index >= 0)
                throw new ArgumentException(String.Format("Item has already been added.  Key being added: \"{0}\".", key));

            Insert(~index, key, value);
        }
 public override void SetByIndex(int index, HtmlOptionTag value)
 {
     lock (root)
         list.SetByIndex(index, value);
 }
 public virtual bool Contains(HtmlOptionTag value)
 {
     return list.ContainsValue(value);
 }
 public override int IndexOfValue(HtmlOptionTag value)
 {
     lock (root)
         return list.IndexOfValue(value);
 }
 public override bool ContainsValue(HtmlOptionTag value)
 {
     lock (root)
         return list.ContainsValue(value);
 }
 public override void Add(string key, HtmlOptionTag value)
 {
     lock (root)
         list.Add(key, value);
 }
            public virtual void Reset()
            {
                if (version != list.version)
                    throw new InvalidOperationException("The collection was modified - enumeration cannot continue.");

                // We can't set the entries equal to null, because they might be value types.
                // Instead, we'll create empty single-element arrays of the right type and copy them
                // over the entries we want to erase.
                string[] tempKey = new string[1];
                HtmlOptionTag[] tempVal = new HtmlOptionTag[1];
                key = tempKey[0];
                value = tempVal[0];
                currentValid = false;
                index = startIndex;
            }
        /// <summary>
        /// Creates a select tag.
        /// </summary>
        /// <param name="currentNode"> The XPathNavigator node.</param>
        /// <returns> A HtmlSelectTag.</returns>
        private HtmlSelectTag CreateSelectTag(XPathNavigator currentNode)
        {
            HtmlSelectTag tag = new HtmlSelectTag();

            tag.Class=currentNode.GetAttribute("class",currentNode.NamespaceURI);
            tag.Id=currentNode.GetAttribute("id",currentNode.NamespaceURI);
            tag.Name=currentNode.GetAttribute("name",currentNode.NamespaceURI);
            tag.OnClick=currentNode.GetAttribute("onclick",currentNode.NamespaceURI);
            tag.Style=currentNode.GetAttribute("style",currentNode.NamespaceURI);
            tag.Title=currentNode.GetAttribute("title",currentNode.NamespaceURI);

            if ( tag.OnClick.Length == 0 )
            {
                tag.OnClick = currentNode.GetAttribute("onClick",currentNode.NamespaceURI);
            }

            if ( currentNode.GetAttribute("multiple",currentNode.NamespaceURI)=="true" )
            {
                tag.Multiple=true;
            }

            tag.Value=currentNode.GetAttribute("value",currentNode.NamespaceURI);

            // fill options nodes
            XPathNodeIterator options = currentNode.SelectChildren(XPathNodeType.Element);

            //tag.Options = new HtmlOptionCollection();

            int i=1;
            while ( options.MoveNext() )
            {
                HtmlOptionTag option = new HtmlOptionTag();
                option.Id=options.Current.GetAttribute("id",options.Current.NamespaceURI);
                if ( options.Current.GetAttribute("selected",options.Current.NamespaceURI)=="true" )
                {
                    option.Selected=true;
                }
                option.Text=options.Current.Value;
                option.Value=options.Current.GetAttribute("value",options.Current.NamespaceURI);

                option.Key = "Option " + i;
                tag.AddOptionTag(option);
                i++;
            }

            return tag;
        }