2013-09-24 45 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 
    } 
} 
相關問題