支持ASP.Net自定义服务器控件中的嵌套元素

时间:2013-09-24 01:00:19

标签: asp.net custom-server-controls

我想创建一个如下所示的自定义服务器控件:

<cc:MyControl prop1="a" prop2="b">
   <cc:MyItem name="xxx">
   <cc:MyItem name="yyy">
   <cc:MyItem name="zzz">
</cc:MyControl>

MyControl当然是作为服务器控件实现的,但我希望MyItem成为子控件。相反,它们应该作为简单的.Net对象存在。我有一个名为MyItem的类,控件有一个名为Items的属性,当在标记中声明MyItem元素时,应该实例化对象并将其添加到集合中。

MSDN上的教程实际上并没有解释这是如何发生的。请参阅:http://msdn.microsoft.com/en-us/library/9txe1d4x.aspx

我想知道:

  1. <cc:MyItem>如何映射到MyItem类?标记中的元素是否必须与对象的类具有相同的名称?
  2. 以声明方式添加MyItems时调用MyItem的哪个构造函数,何时?
  3. 我可以使用哪些集合类型来保存MyItem对象?上面的链接使用ArrayList,但我可以使用强类型列表吗?
  4. 控件是否可以包含多个集合?

1 个答案:

答案 0 :(得分:0)

  1. 使用类名作为标记是很常见的,但如果需要,可以指定其他名称,我不解释更多,如果你想要请发表评论

  2. 当asp.net编译标记时,它使用默认参数less constructor

  3. 你可以使用任何集合类型但是如果你想使用viewstate的好处你的集合类型必须实现IStateManager接口(下面我写了我为自己创建的集合的源代码,具有状态管理支持)

  4. 是的,您的控件可以有多个集合,只需添加所需的属性,如下所示:

  5. (我使用了我的一个代码,请用您想要的名称替换名称) 如果你想首先拥有集合,你必须在你的控件中定义它的属性。 想象一下,我们有一个名为CustomControl的控件,它将Control扩展如下:

    [System.Web.UI.ParseChildrenAttribute(true)]
    [System.Web.UI.PersistChildrenAttribute(false)]
    public class CustomControl : Control{
        private GraphCollection m_graphs;
        [Bindable(false)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public GraphCollection Graphs
        {
            get
            {
                if (this.m_graphs == null) {
                    this.m_graphs = new GraphCollection();
                    if (base.IsTrackingViewState) {
                        this.m_graphs.TrackViewState();
                    }
                }
                return this.m_graphs;
            }
        }
    }
    

    正如您在上面的代码中看到的,CustomControl有一个名为“m_graphs”的字段,其类型为“GraphCollection”,也是一个公开此字段的属性 另请注意其属性PersistenceMode,表示对asp.net属性“Graphs”必须保持为InnerProperty

    另请注意应用于CustomControl类的两个属性 属性ParseChildrenAttribute对asp.net说嵌套标记,必须被视为属性和属性PersistChildrenAttribute对asp.net说嵌套标记不是控件的子级

    在决赛中,我为州管理组件带来了两个源代码 首先是从StateManagedCollection扩展的GraphCollection(这两个类都是由我编写的)

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    
    namespace Farayan.Web.Core
    {
        public class StateManagedCollection<T> : IList, ICollection, IEnumerable, IEnumerable<T>, IStateManager
            where T : class, IStateManager, new()
        {
            // Fields
            private List<T> listItems = new List<T>();
            private bool marked = false;
            private bool saveAll = false;
    
            // Methods
            public void Add(T item)
            {
                this.listItems.Add(item);
                if (this.marked) {
                    //item.Dirty = true;
                }
            }
    
            public void AddRange(T[] items)
            {
                if (items == null) {
                    throw new ArgumentNullException("items");
                }
                foreach (T item in items) {
                    this.Add(item);
                }
            }
    
            public void Clear()
            {
                this.listItems.Clear();
                if (this.marked) {
                    this.saveAll = true;
                }
            }
    
            public bool Contains(T item)
            {
                return this.listItems.Contains(item);
            }
    
            public void CopyTo(Array array, int index)
            {
                this.listItems.CopyTo(array.Cast<T>().ToArray(), index);
            }
    
            public IEnumerator GetEnumerator()
            {
                return this.listItems.GetEnumerator();
            }
    
            public int IndexOf(T item)
            {
                return this.listItems.IndexOf(item);
            }
    
            public void Insert(int index, T item)
            {
                this.listItems.Insert(index, item);
                if (this.marked) {
                    this.saveAll = true;
                }
            }
    
            public void LoadViewState(object state)
            {
                object[] states = state as object[];
                if (state == null || states.Length == 0)
                    return;
                for (int i = 0; i < states.Length; i++) {
                    object itemState = states[i];
                    if (i < Count) {
                        T day = (T)listItems[i];
                        ((IStateManager)day).LoadViewState(itemState);
                    } else {
                        T day = new T();
                        ((IStateManager)day).LoadViewState(itemState);
                        listItems.Add(day);
                    }
                }
            }
    
            public void Remove(T item)
            {
                int index = this.IndexOf(item);
                if (index >= 0)
                    this.RemoveAt(index);
            }
    
            public void RemoveAt(int index)
            {
                this.listItems.RemoveAt(index);
                if (this.marked) {
                    this.saveAll = true;
                }
            }
    
            public object SaveViewState()
            {
                List<object> state = new List<object>(Count);
                foreach (T day in listItems)
                    state.Add(((IStateManager)day).SaveViewState());
                return state.ToArray();
            }
    
            int IList.Add(object item)
            {
                T item2 = (T)item;
                this.listItems.Add(item2);
                return listItems.Count - 1;
            }
    
            bool IList.Contains(object item)
            {
                return this.Contains((T)item);
            }
    
            int IList.IndexOf(object item)
            {
                return this.IndexOf((T)item);
            }
    
            void IList.Insert(int index, object item)
            {
                this.Insert(index, (T)item);
            }
    
            void IList.Remove(object item)
            {
                this.Remove((T)item);
            }
    
            void IStateManager.LoadViewState(object state)
            {
                this.LoadViewState(state);
            }
    
            object IStateManager.SaveViewState()
            {
                return this.SaveViewState();
            }
    
            void IStateManager.TrackViewState()
            {
                this.TrackViewState();
            }
    
            public void TrackViewState()
            {
                this.marked = true;
                for (int i = 0; i < this.Count; i++) {
                    ((IStateManager)this[i]).TrackViewState();
                }
            }
    
            // Properties
            public int Capacity
            {
                get
                {
                    return this.listItems.Capacity;
                }
                set
                {
                    this.listItems.Capacity = value;
                }
            }
    
            public int Count
            {
                get
                {
                    return this.listItems.Count;
                }
            }
    
            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }
    
            public bool IsSynchronized
            {
                get
                {
                    return false;
                }
            }
    
            public T this[int index]
            {
                get
                {
                    return (T)this.listItems[index];
                }
            }
    
            public object SyncRoot
            {
                get
                {
                    return this;
                }
            }
    
            bool IList.IsFixedSize
            {
                get
                {
                    return false;
                }
            }
    
            object IList.this[int index]
            {
                get
                {
                    return this.listItems[index];
                }
                set
                {
                    this.listItems[index] = (T)value;
                }
            }
    
            bool IStateManager.IsTrackingViewState
            {
                get
                {
                    return this.marked;
                }
            }
    
            #region IEnumerable<T> Members
    
            IEnumerator<T> IEnumerable<T>.GetEnumerator()
            {
                return this.listItems.GetEnumerator();
            }
    
            #endregion
    
            #region IEnumerable Members
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
    
            #endregion
        }
    }
    

    和GraphCollection

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Farayan.Web.Core;
    
    namespace Farayan.Web.AmCharts
    {
        public class GraphCollection : StateManagedCollection<Graph>
        {
        }
    }
    

    最后是我们示例中的Graph:

    using System;
    using System.Linq;
    using System.Collections.ObjectModel;
    using System.Drawing;
    using System.Web.UI;
    using System.ComponentModel;
    using Farayan.Web.AmCharts;
    using System.Collections.Generic;
    using Farayan.Web.Controls;
    using System.Runtime;
    using Farayan.Web.Core;
    
    namespace Farayan.Web.AmCharts
    {
        public class Graph : StateManager
        {
            #region Colorize Property
            [Browsable(true)]
            [Localizable(false)]
            [PersistenceMode(PersistenceMode.Attribute)]
            [DefaultValue(false)]
            public virtual bool Colorize
            {
                get { return ViewState["Colorize"] == null ? false : (bool)ViewState["Colorize"]; }
                set { ViewState["Colorize"] = value; }
            }
            #endregion
    
            //==============================
    
            public override void LoadViewState(object state)
            {
                base.LoadViewState(state);
            }
    
            public override object SaveViewState()
            {
                return base.SaveViewState();
            }
        }
    }
    

    您可能会注意到Graph扩展了StateManager类

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Web.UI;
    using Farayan.Web.AmCharts;
    
    namespace Farayan.Web.AmCharts
    {
        public class StateManager : IStateManager
        {
            protected StateBag ViewState = new StateBag();
    
            #region IStateManager Members
    
            public virtual bool IsTrackingViewState
            {
                get { return true; }
            }
    
            public virtual void LoadViewState(object state)
            {
                if (state != null) {
                    ArrayList arrayList = (ArrayList)state;
                    for (int i = 0; i < arrayList.Count; i += 2) {
                        string value = ((IndexedString)arrayList[i]).Value;
                        object value2 = arrayList[i + 1];
                        ViewState.Add(value, value2);
                    }
                }
            }
    
            public virtual object SaveViewState()
            {
                ArrayList arrayList = new ArrayList();
                if (this.ViewState.Count != 0) {
                    IDictionaryEnumerator enumerator = this.ViewState.GetEnumerator();
                    while (enumerator.MoveNext()) {
                        StateItem stateItem = (StateItem)enumerator.Value;
                        //if (stateItem.IsDirty) {
                        if (arrayList == null) {
                            arrayList = new ArrayList();
                        }
                        arrayList.Add(new IndexedString((string)enumerator.Key));
                        arrayList.Add(stateItem.Value);
                        //}
                    }
                }
                return arrayList;
            }
    
            public virtual void TrackViewState()
            {
    
            }
    
            #endregion
    
            #region IStateManager Members
    
            bool IStateManager.IsTrackingViewState
            {
                get { return this.IsTrackingViewState; }
            }
    
            void IStateManager.LoadViewState(object state)
            {
                this.LoadViewState(state);
            }
    
            object IStateManager.SaveViewState()
            {
                return this.SaveViewState();
            }
    
            void IStateManager.TrackViewState()
            {
                this.TrackViewState();
            }
    
            #endregion
        }
    }