溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件

發(fā)布時間:2021-07-16 11:18:12 來源:億速云 閱讀:168 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關(guān)ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

ASP.NET數(shù)據(jù)綁定控件一.回顧

如果你使用過ASP.NET內(nèi)置的數(shù)據(jù)控件(如DataList,Repeater),你一定會這么做

1.設置數(shù)據(jù)源 DataSource屬性

2.調(diào)用數(shù)據(jù)綁定  DataBind方法

3.在控件的不同模板內(nèi)使用綁定語法顯示數(shù)據(jù)

這三步應該是必須要做的

其他更多的

你可能需要對綁定的數(shù)據(jù)進行統(tǒng)一的一些操作(如時間格式化),或者對數(shù)據(jù)的某一項進行操作(對某一項進行格式化),或者需要觸發(fā)模板控件內(nèi)的一些事件(如databound事件).

根據(jù)上面的一些需求,我們需要這樣做

1.對綁定的數(shù)據(jù)進行統(tǒng)一的一些操作: 為數(shù)據(jù)綁定控件定義Item項(表示列表的一條數(shù)據(jù), 如Repeater的RepeaterItem)

2.對數(shù)據(jù)的某一項進行操作: 因為定義了Item項,那你肯定需要一個ItemCollection集合,其可以方便的為你檢索數(shù)據(jù)

3.因為定義了RepeaterItem,原先的EventArgs和CommandEventArgs已經(jīng)無法滿足需求,我們需要自定義委托及其一個為控件提供數(shù)據(jù)的的ItemEventArgs

上面三點有些并非必須定義,如第2點,還需要根據(jù)具體需求來定.但一個完成的控件是需要的.

ASP.NET數(shù)據(jù)綁定控件二.為數(shù)據(jù)控件做好準備

這次的demo為不完整的Datalist控件,來源還是MSDN的例子,我們命名為TemplatedList,此控件未定義ItemCollection集合

好了,根據(jù)上面的分析我們先為TemplatedList提供項和委托及為事件提供數(shù)據(jù)的幾個EventArgs,請看下面類圖

ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件

1.TemplatedListCommandEventArgs為Command事件提供數(shù)據(jù)

2.TemplatedListItemEventArgs為一般項提供數(shù)據(jù)

3.TemplatedListItem表示TemplatedList的項

ASP.NET數(shù)據(jù)綁定控件三.編寫TemplatedList

1.TemplatedList主要功能簡介

提供一個ItemTemplate模板屬性,提供三種不同項樣式,ItemCommand 事件冒泡事件及4個事件

ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件

2.實現(xiàn)主要步驟

以下為必須

(1)控件必須實現(xiàn) System.Web.UI.INamingContainer 接口

(2)定義至少一個模板屬性

(3)定義DataSource數(shù)據(jù)源屬性

(4)定義控件項DataItem,即模板的一個容器

(5)重寫DataBind 方法及復合控件相關(guān)方法(模板控件為特殊的復合控件)

當然還有其他額外的屬性,樣式,事件

3.具體實現(xiàn)

下面我們來具體看實現(xiàn)方法

(1)定義控件成員屬性

#region 靜態(tài)變量           private static readonly object EventSelectedIndexChanged = new object();          private static readonly object EventItemCreated = new object();          private static readonly object EventItemDataBound = new object();          private static readonly object EventItemCommand = new object();          #endregion           成員變量#region 成員變量          private IEnumerable dataSource;          private TableItemStyle itemStyle;          private TableItemStyle alternatingItemStyle;          private TableItemStyle selectedItemStyle;          private ITemplate itemTemplate;          #endregion           控件屬性#region 控件屬性           [          Category("Style"),          Description("交替項樣式"),          DesignerSerializationVisibility(DesignerSerializationVisibility.Content),          NotifyParentProperty(true),          PersistenceMode(PersistenceMode.InnerProperty),          ]          public virtual TableItemStyle AlternatingItemStyle          {              get             {                  if (alternatingItemStyle == null)                  {                      alternatingItemStyle = new TableItemStyle();                      if (IsTrackingViewState)                          ((IStateManager)alternatingItemStyle).TrackViewState();                  }                  return alternatingItemStyle;              }          }            [          Category("Style"),          Description("一般項樣式"),          DesignerSerializationVisibility(DesignerSerializationVisibility.Content),          NotifyParentProperty(true),          PersistenceMode(PersistenceMode.InnerProperty),          ]          public virtual TableItemStyle ItemStyle          {              get             {                  if (itemStyle == null)                  {                      itemStyle = new TableItemStyle();                      if (IsTrackingViewState)                          ((IStateManager)itemStyle).TrackViewState();                  }                  return itemStyle;              }          }           [           Category("Style"),           Description("選中項樣式"),           DesignerSerializationVisibility(DesignerSerializationVisibility.Content),           NotifyParentProperty(true),           PersistenceMode(PersistenceMode.InnerProperty),           ]          public virtual TableItemStyle SelectedItemStyle          {              get             {                  if (selectedItemStyle == null)                  {                      selectedItemStyle = new TableItemStyle();                      if (IsTrackingViewState)                          ((IStateManager)selectedItemStyle).TrackViewState();                  }                  return selectedItemStyle;              }          }             [          Bindable(true),          Category("Appearance"),          DefaultValue(-1),          Description("The cell padding of the rendered table.")          ]          public virtual int CellPadding          {              get             {                  if (ControlStyleCreated == false)                  {                      return -1;                  }                  return ((TableStyle)ControlStyle).CellPadding;              }              set             {                  ((TableStyle)ControlStyle).CellPadding = value;              }          }           [          Bindable(true),          Category("Appearance"),          DefaultValue(0),          Description("The cell spacing of the rendered table.")          ]          public virtual int CellSpacing          {              get             {                  if (ControlStyleCreated == false)                  {                      return 0;                  }                  return ((TableStyle)ControlStyle).CellSpacing;              }              set             {                  ((TableStyle)ControlStyle).CellSpacing = value;              }          }             [          Bindable(true),          Category("Appearance"),          DefaultValue(GridLines.None),          Description("The grid lines to be shown in the rendered table.")          ]          public virtual GridLines GridLines          {              get             {                  if (ControlStyleCreated == false)                  {                      return GridLines.None;                  }                  return ((TableStyle)ControlStyle).GridLines;              }              set             {                  ((TableStyle)ControlStyle).GridLines = value;              }          }           [          Bindable(true),          Category("Data"),          DefaultValue(null),          Description("數(shù)據(jù)源"),          DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)          ]          public IEnumerable DataSource          {              get             {                  return dataSource;              }              set             {                  dataSource = value;              }          }            [          Browsable(false),          DefaultValue(null),          Description("項模板"),          PersistenceMode(PersistenceMode.InnerProperty),          TemplateContainer(typeof(TemplatedListItem))          ]          public virtual ITemplate ItemTemplate          {              get             {                  return itemTemplate;              }              set             {                  itemTemplate = value;              }          }            [          Bindable(true),          DefaultValue(-1),          Description("選中項索引,默認為-1")          ]          public virtual int SelectedIndex          {              get             {                  object o = ViewState["SelectedIndex"];                  if (o != null)                      return (int)o;                  return -1;              }              set             {                  if (value < -1)                  {                      throw new ArgumentOutOfRangeException();                  }                  //獲取上次選中項                  int oldSelectedIndex = SelectedIndex;                  ViewState["SelectedIndex"] = value;                   if (HasControls())                  {                      Table table = (Table)Controls[0];                      TemplatedListItem item;                       //第一次選中項不執(zhí)行                      if ((oldSelectedIndex != -1) && (table.Rows.Count > oldSelectedIndex))                      {                          item = (TemplatedListItem)table.Rows[oldSelectedIndex];                          //判斷項類型,為了將選中項還原為數(shù)據(jù)項                          if (item.ItemType != ListItemType.EditItem)                          {                              ListItemType itemType = ListItemType.Item;                              if (oldSelectedIndex % 2 != 0)                                  itemType = ListItemType.AlternatingItem;                              item.SetItemType(itemType);                          }                      }                      //第一次執(zhí)行此項,并一直執(zhí)行                      if ((value != -1) && (table.Rows.Count > value))                      {                          item = (TemplatedListItem)table.Rows[value];                          item.SetItemType(ListItemType.SelectedItem);                      }                  }              }          }              #endregion

成員如下(可以看上面類圖)

1.三個項樣式和三個樣式屬性

2.公開DataSource數(shù)據(jù)源屬性,一個模板屬性

3.SelectedIndex索引屬性

前面的相信大家都很容易明白,其中的三個項樣式我們需要為其重寫視圖狀態(tài)管理,不熟悉可以看以前的隨筆,這里不再重復.

SelectedIndex屬性比較復雜,這里重點介紹此屬性

SelectedIndex索引屬性默認為-1,

我給出了注釋,在賦值前先記錄下了上次的選中項,為恢復樣式而做準備

//獲取上次選中項   int oldSelectedIndex = SelectedIndex;   ViewState["SelectedIndex"] = value;

當?shù)谝淮胃腟electedIndex屬性時只執(zhí)行下列代碼(將此項標記為選中項),因為初始化時的沒有oldSelectedIndex,不需要恢復樣式

//第一次執(zhí)行此項,并一直執(zhí)行                      if ((value != -1) && (table.Rows.Count > value))                      {                          item = (TemplatedListItem)table.Rows[value];                          item.SetItemType(ListItemType.SelectedItem);                      }

再次執(zhí)行時,恢復oldSelectedIndex選中項樣式

//第一次選中項不執(zhí)行  if ((oldSelectedIndex != -1) && (table.Rows.Count > oldSelectedIndex))  {      item = (TemplatedListItem)table.Rows[oldSelectedIndex];      //判斷項類型,為了將選中項還原為數(shù)據(jù)項      if (item.ItemType != ListItemType.EditItem)      {          ListItemType itemType = ListItemType.Item;          if (oldSelectedIndex % 2 != 0)              itemType = ListItemType.AlternatingItem;          item.SetItemType(itemType);      }  }

相信這樣的解釋你會明白

(2)定義控件成員事件

我們可以用上剛才我們聲明的委托了,即然你定義了這么多事件,就該為其安排觸發(fā)的先后.所以這個要特別注意,等下會再次提到.

#region 事件          protected virtual void OnItemCommand(TemplatedListCommandEventArgs e)          {              TemplatedListCommandEventHandler onItemCommandHandler = (TemplatedListCommandEventHandler)Events[EventItemCommand];              if (onItemCommandHandler != null) onItemCommandHandler(this, e);          }           protected virtual void OnItemCreated(TemplatedListItemEventArgs e)          {              TemplatedListItemEventHandler onItemCreatedHandler = (TemplatedListItemEventHandler)Events[EventItemCreated];              if (onItemCreatedHandler != null) onItemCreatedHandler(this, e);          }           protected virtual void OnItemDataBound(TemplatedListItemEventArgs e)          {              TemplatedListItemEventHandler onItemDataBoundHandler = (TemplatedListItemEventHandler)Events[EventItemDataBound];              if (onItemDataBoundHandler != null) onItemDataBoundHandler(this, e);          }           protected virtual void OnSelectedIndexChanged(EventArgs e)          {              EventHandler handler = (EventHandler)Events[EventSelectedIndexChanged];              if (handler != null) handler(this, e);          }           [          Category("Action"),          Description("Raised when a CommandEvent occurs within an item.")          ]          public event TemplatedListCommandEventHandler ItemCommand          {              add              {                  Events.AddHandler(EventItemCommand, value);              }              remove              {                  Events.RemoveHandler(EventItemCommand, value);              }          }           [          Category("Behavior"),          Description("Raised when an item is created and is ready for customization.")          ]          public event TemplatedListItemEventHandler ItemCreated          {              add              {                  Events.AddHandler(EventItemCreated, value);              }              remove              {                  Events.RemoveHandler(EventItemCreated, value);              }          }           [          Category("Behavior"),          Description("Raised when an item is data-bound.")          ]          public event TemplatedListItemEventHandler ItemDataBound          {              add              {                  Events.AddHandler(EventItemDataBound, value);              }              remove              {                  Events.RemoveHandler(EventItemDataBound, value);              }          }           [          Category("Action"),          Description("Raised when the SelectedIndex property has changed.")          ]          public event EventHandler SelectedIndexChanged          {              add              {                  Events.AddHandler(EventSelectedIndexChanged, value);              }              remove              {                  Events.RemoveHandler(EventSelectedIndexChanged, value);              }          }          #endregion

(3)關(guān)鍵實現(xiàn)

我們?yōu)榭丶峁┝诉@么多東西,剩下的事情就是要真正去實現(xiàn)功能了

1.重寫DataBind方法

當控件綁定數(shù)據(jù)時首先會執(zhí)行此方法觸發(fā)DataBinding事件

//控件執(zhí)行綁定時執(zhí)行  public override void DataBind()  {       base.OnDataBinding(EventArgs.Empty);       //移除控件      Controls.Clear();      //清除視圖狀態(tài)信息      ClearChildViewState();       //創(chuàng)建一個帶或不帶指定數(shù)據(jù)源的控件層次結(jié)構(gòu)      CreateControlHierarchy(true);      ChildControlsCreated = true;       TrackViewState();  }

2.CreateControlHierarchy方法

/**//// <summary>   /// 創(chuàng)建一個帶或不帶指定數(shù)據(jù)源的控件層次結(jié)構(gòu)   /// </summary>   /// <param name="useDataSource">指示是否要使用指定的數(shù)據(jù)源</param>   //注意:當?shù)诙螆?zhí)行數(shù)據(jù)綁定時,會執(zhí)行兩遍   private void CreateControlHierarchy(bool useDataSource)   {       IEnumerable dataSource = null;       int count = -1;         if (useDataSource == false)       {           // ViewState must have a non-null value for ItemCount because this is checked            //  by CreateChildControls.           count = (int)ViewState["ItemCount"];           if (count != -1)           {               dataSource = new DummyDataSource(count);           }       }       else      {           dataSource = this.dataSource;       }        //根據(jù)項類型開始創(chuàng)建子控件       if (dataSource != null)       {           Table table = new Table();           Controls.Add(table);            //選中項索引           int selectedItemIndex = SelectedIndex;           //項索引           int index = 0;           //項數(shù)量           count = 0;           foreach (object dataItem in dataSource)           {                ListItemType itemType = ListItemType.Item;               if (index == selectedItemIndex)               {                                     itemType = ListItemType.SelectedItem;               }               else if (index % 2 != 0)               {                   itemType = ListItemType.AlternatingItem;               }                //根據(jù)不同項索引創(chuàng)建樣式               CreateItem(table, index, itemType, useDataSource, dataItem);               count++;               index++;           }       }       //執(zhí)行綁定時執(zhí)行時執(zhí)行       if (useDataSource)       {           //保存項數(shù)量           ViewState["ItemCount"] = ((dataSource != null) ? count : -1);       }   }     //創(chuàng)建項   private TemplatedListItem CreateItem(Table table, int itemIndex, ListItemType itemType, bool dataBind, object dataItem)   {       TemplatedListItem item = new TemplatedListItem(itemIndex, itemType);       TemplatedListItemEventArgs e = new TemplatedListItemEventArgs(item);        if (itemTemplate != null)       {           itemTemplate.InstantiateIn(item.Cells[0]);       }       if (dataBind)       {           item.DataItem = dataItem;       }       //注意事件觸發(fā)順序       OnItemCreated(e);       table.Rows.Add(item);        if (dataBind)       {           item.DataBind();           OnItemDataBound(e);            item.DataItem = null;       }        return item;   }

CreateItem方法輔助用于創(chuàng)建項模板,此處注意事件觸發(fā)順序,上面已經(jīng)提到過

此方法根據(jù)項索引創(chuàng)建控件中不同的Item項 ,ViewState["ItemCount"]表示項的數(shù)量,第一次觸發(fā)時或者重新執(zhí)行DataBind方法時方法參數(shù)為true,并在初始化以后(回發(fā)期間)CreateChildControls方法會調(diào)用此方法,其參數(shù)為false

數(shù)據(jù)源不再是實際的數(shù)據(jù)源,而是新定義的DummyDataSource,其主要實現(xiàn)了一個迭代

internal sealed class DummyDataSource : ICollection      {           private int dataItemCount;           public DummyDataSource(int dataItemCount)          {              this.dataItemCount = dataItemCount;          }           public int Count          {              get             {                  return dataItemCount;              }          }           public bool IsReadOnly          {              get             {                  return false;              }          }           public bool IsSynchronized          {              get             {                  return false;              }          }           public object SyncRoot          {              get             {                  return this;              }          }           public void CopyTo(Array array, int index)          {              for (IEnumerator e = this.GetEnumerator(); e.MoveNext(); )                  array.SetValue(e.Current, index++);          }           public IEnumerator GetEnumerator()          {              return new DummyDataSourceEnumerator(dataItemCount);          }           private class DummyDataSourceEnumerator : IEnumerator          {               private int count;              private int index;               public DummyDataSourceEnumerator(int count)              {                  this.count = count;                  this.index = -1;              }               public object Current              {                  get                 {                      return null;                  }              }               public bool MoveNext()              {                  index++;                  return index < count;              }               public void Reset()              {                  this.index = -1;              }          }      }

原因很明顯,為了減少對數(shù)據(jù)源的訪問,所以我們平時操作數(shù)據(jù)的時候,必須重新執(zhí)行DataBind方法,原因就在此

好了,到了這里差不多主要的事情我們已經(jīng)完成.接著把剩下的也完成

3.呈現(xiàn)

又到了Render方法這里了

此方法體只要執(zhí)行了PrepareControlHierarchy方法,不同的方法做不同的事情,CreateControlHierarchy方法根據(jù)索引值指定了不同的項,PrepareControlHierarchy則為不同項呈現(xiàn)不同的樣式效果

//為不同類型項加載樣式  private void PrepareControlHierarchy()  {      if (HasControls() == false)      {          return;      }       Debug.Assert(Controls[0] is Table);      Table table = (Table)Controls[0];       table.CopyBaseAttributes(this);      if (ControlStyleCreated)      {          table.ApplyStyle(ControlStyle);      }       // The composite alternating item style; do just one      // merge style on the actual item.      Style altItemStyle = null;      if (alternatingItemStyle != null)      {          altItemStyle = new TableItemStyle();          altItemStyle.CopyFrom(itemStyle);          altItemStyle.CopyFrom(alternatingItemStyle);      }      else     {          altItemStyle = itemStyle;      }       int rowCount = table.Rows.Count;      for (int i = 0; i < rowCount; i++)      {          TemplatedListItem item = (TemplatedListItem)table.Rows[i];          Style compositeStyle = null;          //根據(jù)不同項加載不同樣式          switch (item.ItemType)          {              case ListItemType.Item:                  compositeStyle = itemStyle;                  break;               case ListItemType.AlternatingItem:                  compositeStyle = altItemStyle;                  break;               case ListItemType.SelectedItem:                  {                      compositeStyle = new TableItemStyle();                       if (item.ItemIndex % 2 != 0)                          compositeStyle.CopyFrom(altItemStyle);                      else                         compositeStyle.CopyFrom(itemStyle);                      compositeStyle.CopyFrom(selectedItemStyle);                  }                  break;          }           if (compositeStyle != null)          {              item.MergeStyle(compositeStyle);          }      }  }   //控件呈現(xiàn)  protected override void Render(HtmlTextWriter writer)  {      // Apply styles to the control hierarchy      // and then render it out.       // Apply styles during render phase, so the user can change styles      // after calling DataBind without the property changes ending      // up in view state.      PrepareControlHierarchy();       RenderContents(writer);  }

終于差不多了,經(jīng)過這么多步驟,我們終于完成了,讓我們來使用控件,看一下效果

ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件

以上就是ASP.NET中怎么實現(xiàn)一個數(shù)據(jù)綁定控件,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI