【问题标题】:Supporting nested elements in ASP.Net Custom Server Controls支持 ASP.Net 自定义服务器控件中的嵌套元素
【发布时间】:2013-09-24 01:00:18
【问题描述】:

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

<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. &lt;cc:MyItem&gt; 如何映射到 MyItem 类?标记中的元素是否必须与对象的类同名?
  2. 以声明方式添加 MyItem 时调用 MyItem 的哪个构造函数,何时调用?
  3. 允许我使用哪些集合类型来保存 MyItem 对象?上面的链接使用了 ArrayList,但是我可以使用强类型的 List 来代替吗?
  4. 一个控件是否可以包含多个集合?

【问题讨论】:

    标签: asp.net custom-server-controls


    【解决方案1】:
    1. 使用类名进行标记是很常见的,但是如果你愿意,你可以指定另一个名字,我不再解释,如果你想请评论

    2. asp.net编译标记时,使用默认无参数构造函数

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

    (我使用了我的一个代码,请将名称替换为您想要的名称) 如果你想首先收集你必须在你的控件中定义它的属性。 假设我们有一个名为 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>
        {
        }
    }
    

    最后是我们示例中的图表:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 2011-03-17
      • 1970-01-01
      相关资源
      最近更新 更多