Estendendo o BoundField

Uma das facilidades que o esquema POO provê é a criação de classes a partir de outras existentes, a fim de incorporarmos (ou até restringirmos) funcionalidades, através da herança.

No Asp.Net temos os controles GridView e DetailsView, muito úteis por simplificar o processo de listar e editar entradas em um banco de dados, por exemplo. Nelas temos os controles de campo, ou coluna, tais como o BoundField, ButtonField e TemplateField entre outros.

Se você já é familiar à utilização destes controles, sabe como eles acabam por ser limitados. Caso seja necessário uma simples validação em um campo no DetaisView é preciso substituir o BoundField por um TemplateField, e colocar em seu interior algo como um TextBox mais um RequiredFieldValidator ou algum outro controle de validação.

Pegue um formulário com uns 30 campos e verá o tamanho do trabalho braçal necessário para modificar o DetailsView. Se o lema da MS é criar sistemas sem perder tempo escrevendo linhas de código redundantes, espero também não perder este tempo substituindo tags no código.

Aí que entra a herança, podemos facilmente estender um BoundField e incorporar nele um validador como o RequiredFieldValidator. Assim podemos marcar nosso campo como obrigatório apenas marcando um atributo da tag como true.

Por exemplo, estendendo o BoundField em uma classe denominada MyBoundField e adicionando uma propriedade denominada RequiredField podemos substituir a tag:

“numCNPJ” HeaderText=“CNPJ” SortExpression=“numCNPJ” />
Por:

“numCNPJ” HeaderText=“CNPJ” SortExpression=“numCNPJ” RequiredField=“true” />
Ao invés da prolixa:

“CNAE” SortExpression=“numCNPJ”>

“TextBox1” runat=“server” Text=‘’>
“RequiredFieldValidator1” runat=“server” ControlToValidate=“TextBox1” ErrorMessage=“Campo requerido!” />


“TextBox2” runat=“server” Text=‘’>
“RequiredFieldValidator2” runat=“server” ControlToValidate=“TextBox2” ErrorMessage=“Campo requerido!” />




O código da classe MyBoundField é o seguinte:

using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.ComponentModel; namespace Custom.DataBinding { ///

/// A custom BoundField that agregates validators /// public class MyBoundField : System.Web.UI.WebControls.BoundField { protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState) { base.InitializeDataCell(cell, rowState); if (this.RequiredField) { if (cell.Controls[0] is TextBox) { TextBox box = cell.Controls[0] as TextBox; box.ID = this.DataField; } RequiredFieldValidator reqField = new RequiredFieldValidator(); reqField.ControlToValidate = this.DataField; reqField.Text = "*"; reqField.ErrorMessage = this.HeaderText + " is required."; reqField.Display = ValidatorDisplay.Dynamic; cell.Controls.Add(reqField); } } /// /// Require Validation /// /// [Browsable(true)] public bool RequiredField { get { if (ViewState["RequiredField"] == null) return false; return (bool)ViewState["RequiredField"]; } set { ViewState["RequiredField"] = value; } } } }

Para utilizá-la em sua solução, basta criar um projeto que contenha a classe acima e colocar a diretiva Register na página aspx ou ascx:

@ Register Assembly=“NomeDoAssembly” Namespace=“Custom.DataBinding” TagPrefix=“cc1”%>
Ou seu equivalente no Web.config.

Nota: Infelizmente parece que o autocompletar do intellisense não funciona ao utilizar o MyBoundField, limitando bastante os prós deste tipo de abordagem. Verificarei com mais cuidado o porquê disto. Tem alguma informação aqui: intellisense in html view. O caso é que se for necessário criar um XSD contendo a definição do novo controle, será muito difícil utilizar estas classes estendidas durante o desenvolvimento.