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:
Por:
Ao invés da prolixa:
<EditItemTemplate>
<asp:TextBox ID=“TextBox1″ runat=“server” Text=‘<%# Bind(“numCNPJ”) %>’></asp:TextBox>
<asp:RequiredFieldValidator ID=“RequiredFieldValidator1″ runat=“server” ControlToValidate=“TextBox1″ ErrorMessage=“Campo requerido!” />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID=“TextBox2″ runat=“server” Text=‘<%# Bind(“numCNPJ”) %>’></asp:TextBox>
<asp:RequiredFieldValidator ID=“RequiredFieldValidator2″ runat=“server” ControlToValidate=“TextBox2″ ErrorMessage=“Campo requerido!” />
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID=“Label1″ runat=“server” Text=‘<%# Bind(“numCNPJ”) %>’></asp:Label>
</ItemTemplate>
</asp:TemplateField>
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
{
/// <summary>
/// A custom BoundField that agregates validators
/// </summary>
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);
}
}
/// <summary>
/// Require Validation
/// </summary>
///
[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:
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.