0

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

<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,但是我可以使用强类型的 List 来代替吗?
  4. 一个控件是否可以包含多个集合?
4

1 回答 1

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

  2. 当 asp.net 编译标记时,它使用默认参数少的构造函数

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

  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
    }
}
于 2014-04-30T12:48:03.713 回答