2013-09-24 47 views
0

我想创建一个自定义服务器控件,看起来像这样:支持嵌套的元素在ASP.Net自定义服务器控件

<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. 控件是否可能包含多个集合?

回答

0
  1. 它是如此普遍使用的类名称的标记,但如果你愿意,你可以指定另一个名字,我不解释更多,如果你想请评论

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

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

  4. 是的,你的控制可以有多个集合,只需添加所需要的属性如下:

(我用我的代码中的一个,请您想要的名称替换名称),如果你想拥有 首先收集你必须在你的控制中定义它的属性。 想象我们有一个控制命名CustomControl,由于下方延伸控制:

[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财产“图”说,必须坚持为InnerProperty

也请注意应用于CustomControl类 属性ParseChildrenAttribute两个属性说来asp.net是嵌套标记,必须被视为属性和属性PersistChildr enAttribute对asp说。网:嵌套标记是无法控制的孩子

在最后,我把两个源代码状态管理组件 首先从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 extends 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 
    } 
} 
相关问题