Custom Control con il supporto al databind per ASP.NET 2.0

di Daniele Bochicchio, in ASP.NET 2.0, Custom Control, DataBinding,

ASP.NET 2.0 introduce diverse novità per quanto riguarda la creazione di custom control con supporto per il databinding.
Se si opta per avere un maggior controllo su quello che il custom control deve fare, generalmente si sfruttano la classi DataBoundControl o CompositeDataBoundControl come base, derivando da una di queste due.
Così facendo, viene fornito il supporto per l'interfaccia IDataSource, per la proprietà DataSource (che accetta un tipo che implementi uno tra IList, IEnumerable e ICollection), per la nuova proprietà DataSourceID e per la sintassi di binding, contraddistinta da questa sintassi:

<%#...%>

CompositeDataBoundControl è la scelta da preferire quando si ha la necessità di creare un controllo che sia composto da un numero ripetuto di informazioni, come è il caso che prendiamo in esame, che consiste nella creazione di un controllo simile al Repeater di ASP.NET, ma più semplice e leggero nell'implementazione.

CompositeDataBoundControl, rispetto a DataBoundControl, contiene il 90% di quello che è necessario implementare per avere un custom control del genere, con il supporto per la proprietà DataSourceID a garantire anche la possibilità di utilizzare il designer di Visual Studio per specificare la sorgente dati, e tutte le funzionalità necessarie per recuperare lo stato dei controlli figli direttamente dal ViewState, in maniera automatica per lo sviluppatore.

Il controllo in questione potrebbe dunque essere implementato in questo modo:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.ComponentModel;

namespace ASPItalia.com.Web.UI.Controls
{
  [ParseChildren(true)]
  public class SimpleRepeater : CompositeDataBoundControl
  {
    private ITemplate _itemTemplate;

    [
      Browsable(false),
      PersistenceMode(PersistenceMode.InnerProperty),
      DefaultValue(typeof(ITemplate), ""),
      TemplateContainer(typeof(SimpleRepeaterRow), BindingDirection.TwoWay)
    ]

    public ITemplate ItemTemplate
    {
      get { return _itemTemplate; }
      set { _itemTemplate = value; }
    }

    protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
    {
      int count = 0;

      // enumero la sorgente, per ricreare i template
      foreach (object dataItem in dataSource)
      {
        // creo un nuovo controllo che farà da contenitore dei dati
        SimpleRepeaterRow container = new SimpleRepeaterRow(dataItem, count, count);
        this.Controls.Add(container);

        ItemTemplate.InstantiateIn(container);

        // effettuo il bind del singolo controllo
        if (dataBinding)
        {
          container.DataItem = dataItem;
          if (!IsPostBack)
            container.DataBind();
          container.DataItem = null;
         }

        // e l'aggiungo al controllo padre
        this.Controls.Add(container);
        count++;
      }

      return count;
    }
  }
}

Perchè questo controllo possa funzionare, ha bisogno di uno ulteriore che faccia da contenitore per il template, che nell'esempio è rappresentato da SimpleRepeaterRow, una classe che implementa l'interfaccia IDataItemContainer, così da rendere possibile, all'interno del template, l'accesso ad una proprietà di nome DataItem, che consente di recuperare i dati associati a quella particolare iterazione sui dati associati.

using System;
using System.Collections.Generic;
using System.Web.UI;

namespace ASPItalia.com.Web.UI.Controls
{
  public class SimpleRepeaterRow : Control, IDataItemContainer, INamingContainer
  {
    private object _dataItem;
    private int _dataItemIndex;
    private int _displayIndex;

    public SimpleRepeaterRow(object dataItem, int dataItemIndex, int displayIndex)
    {
      _dataItem = dataItem;
      _dataItemIndex = dataItemIndex;
      _displayIndex = displayIndex;
    }

    public object DataItem
    {
      get { return _dataItem; }
      set { _dataItem = value; }
    }

    public int DataItemIndex
    {
      get { return _dataItemIndex; }
    }

    public int DisplayIndex
    {
      get { return _displayIndex;}
    }
  }
}

Una volta implementato il tutto, è possibile utilizzare questo controllo come se fosse un normale Repeater, in questo modo:

<asp:ObjectDataSource ID="MySource" runat="server" SelectMethod="GetAll" TypeName="DummySource" />
<aspitalia:SimpleRepeater ID="MyRepeater" runat="server" DataSourceID="MySource">
<ItemTemplate>
  <li><%#Eval("FirstName") %> <%#DataBinder.Eval(Container.DataItem, "LastName")%></li>
</ItemTemplate>
</aspitalia:SimpleRepeater>

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi