sábado, 29 de maio de 2010

Dot Net: Como fazer um controle TextBox

O .Net Framework oferece um recurso chamado controle ou componente. Que são todos os itens que você ve na aba Toolbox (TextBox, Button, LinkButton, GridView, ...) do Visual Studio.

O que é mais interessante nisso e que facilita muito é que você pode criar componentes personalizados, por exemplo, inputs personalizados com máscaras, ModalPopUp, Abas... .

A vantagem de usar um controle, é que é só clicar e arrastar para onde precisar e configurar os parametros, não precisa ficar chamando arquivos ou métodos do javascript, digitando ou copiando linhas e linhas de html, ...



O exemplo abaixo é de um controle TextBox com máscara.

Eu fiz esse controle em C# e VB.Net. Se você apenas for usar o controle sem modificar, não tem diferença da linguagem usada.

Para criar esse TextBox é necessário criar um projeto separado. Siga os passos abaixo:



1 - Crie um projeto do tipo ASP.NET Web Application.

2 - Crie uma classe que será o controle TextBox personalizado. Eu usei o nome "ControleTextBox".

O código dessa classe em C#

A mesma classe em VB.NET
'Isso serve para adicionar o arquivo .js no controle. Para usar isso, deve mudar o valor da propriedade "Build Action" para "Embedded Resource" do arquivo.

Public Class ControleTextBox
    Inherits TextBox

    Private _Tipo As EnumTipo = EnumTipo.Nomal

    'O Enum cria uma lista de opções
    Public Enum EnumTipo
        Nomal
        SoNumero
        CPF
    End Enum

    Public Property Tipo() As EnumTipo
        Get
            Return _Tipo
        End Get
        Set(ByVal value As EnumTipo)
            _Tipo = value
        End Set
    End Property

    Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(ByVal value As String)
            'Ao passar um valor pro TextBox, será automaticamente formatado.
            Select Case Tipo
                Case EnumTipo.CPF
                    MyBase.Text = Regex.Replace(String.Format("{0,-11}", value), "^(\d{3})(\d{3})(\d{3})(\d{2})$", "$1.$2.$3-$4")
                Case Else
                    MyBase.Text = value
            End Select
        End Set
    End Property

    Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
        MyBase.OnPreRender(e)

        'Chama o arquivo .js para a pagina.
        Page.ClientScript.RegisterClientScriptResource(GetType(ControleTextBox), "VB.Net_Controle_TextBox.ControleTextBox.js")

        Select Case _Tipo
            Case EnumTipo.SoNumero
                Me.Attributes.Add("onkeydown", "Formata_SoNumero(this, event);")
                Me.Attributes.Add("onkeyup", "Formata_SoNumero(this, event);")

            Case EnumTipo.CPF
                Me.Attributes.Add("onkeydown", "Formata_CPF(this, event);")
                Me.Attributes.Add("onkeyup", "Formata_CPF(this, event);")
                Me.MaxLength = 14
                Me.Width = 90

        End Select
    End Sub

End Class

3 - Crie um arquivo Javascript, com o nome ControleTextBox.js.


function Formata_SoNumero(th) {
    th.value = th.value.replace(/[^\d]/gi, "");
}

function Formata_CPF(th, e) {
    th.value = th.value.replace(/[^\d{1}]$/gi, "");
    if ((window.event ? e.keyCode : e.which) != 8) {
        if (th.value.length == 3) th.value = th.value + '.';
        if (th.value.length == 7) th.value = th.value + '.';
        if (th.value.length == 11) th.value = th.value + '-';
    }
}



Obs.: Nas propriedades desse arquivo, mude o valor do "Build Action" para "Embedded Resource"



4 - De um "Build" no projeto do controle para criar a DLL e onde for usar o controle é só adicionar essa dll como referência.

5 - Se o controle não aparecer no Toolbox é só clicar com botão direita em uma parte livre da toolbox, ir em Choose Items.... Na janela "Choose Toolbox Items", clique em "Browse" e selecione a dll e depois clique em OK.

Depois de ter feito isso, é só arrastar o controle para a tela, ir no menu Properties do controle e mudar o Tipo.



Projeto de exemplo no Google Code.


sábado, 1 de maio de 2010

Dot Net: Ler e gravar imagem no banco de dados

Esse exemplo mostra como enviar uma imagem com o controle FileUpload e salvar em uma tabela do banco de dados Sql Server e como recuperar essa imagem usando um Generic Handler (ASHX).

Gravando a imagem no banco de dados
Exemplo em C#:

protected void btnEnviar_Click(object sender, EventArgs e)
{
SqlConnection conexao = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlConnectionStringSqlServer"].ConnectionString);
try
{
conexao.Open();
SqlCommand comando = new SqlCommand("INSERT INTO [DotNet_Gravar_e_Ler_Imagem_no_Banco_de_dados] (Imagem) VALUES (@Imagem) ", conexao);
comando.Parameters.Add("@Imagem", SqlDbType.Image).Value = FileUploadImagem.FileBytes; // O "FileUploadImagem" é a ID do controle FileUpload
comando.ExecuteNonQuery();
GridView1.DataBind();
}
finally
{
conexao.Close();
}
}


Exemplo em VB.NET:

Protected Sub btnEnviar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnEnviar.Click
Dim conexao As New SqlConnection(ConfigurationManager.ConnectionStrings("SqlConnectionStringSqlServer").ConnectionString)
Try
conexao.Open()
Dim comando As New SqlCommand("INSERT INTO [DotNet_Gravar_e_Ler_Imagem_no_Banco_de_dados] (Imagem) VALUES (@Imagem) ", conexao)
comando.Parameters.Add("@Imagem", Data.SqlDbType.Image).Value = FileUploadImagem.FileBytes ' O "FileUploadImagem" é a ID do controle FileUpload
comando.ExecuteNonQuery()
GridView1.DataBind()
Finally
conexao.Close()
End Try
End Sub





Recuperando a imagem do banco

Para recuperar ou transformar de volta em imagem o que está no banco de dados, é usado um arquivo do tipo "Generic Handler", com o seguinte código.

Exemplo em C#:

public void ProcessRequest (HttpContext context) {
if(string.IsNullOrEmpty(context.Request.QueryString["id"])) {
context.Response.ContentType = "text/plain";
context.Response.Write("Está faltando a querystring id.");
} else {
context.Response.ContentType = "image/jpeg";
SqlConnection conexao = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlConnectionStringSqlServer"].ConnectionString);
try {
conexao.Open();
SqlCommand comando = new SqlCommand("SELECT Imagem FROM DotNet_Gravar_e_Ler_Imagem_no_Banco_de_dados WHERE IDImagem = @IDImagem", conexao);
comando.CommandType = CommandType.Text;
comando.Parameters.Add("@IDImagem", SqlDbType.Int).Value = context.Request.QueryString["id"];
context.Response.Clear();
context.Response.BinaryWrite((byte[])comando.ExecuteScalar());
} finally{
conexao.Close();
}
}
}


Exemplo em VB.NET:

Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
If String.IsNullOrEmpty(context.Request.QueryString("id")) Then
context.Response.ContentType = "text/plain"
context.Response.Write("Está faltando a querystring id.")
Else
context.Response.ContentType = "image/jpg"
Dim conexao As New SqlConnection(ConfigurationManager.ConnectionStrings("SqlConnectionStringSqlServer").ConnectionString)
Try
conexao.Open()
Dim comando As New SqlCommand("SELECT Imagem FROM DotNet_Gravar_e_Ler_Imagem_no_Banco_de_dados WHERE IDImagem = @IDImagem", conexao)
comando.CommandType = CommandType.Text
comando.Parameters.Add("@IDImagem", SqlDbType.Int).Value = context.Request.QueryString("id")
context.Response.Clear()
context.Response.BinaryWrite(comando.ExecuteScalar)
Catch ex As Exception

Finally
conexao.Close()
End Try
End If
End Sub




Se você quiser mostrar as imagens direto na gridview, é só adicionar uma coluna na grid e passar o link do .ASHX com a querystring "id". Igual ao exemplo abaixo:







Porém essa não é a melhor solução, porque a cada linha da grid o ASHX vai fazer uma conexão no banco para retorna a imagem. Para isso, a melhor solução é salvar a imagem em um diretório e guardar apenas o link no banco de dados.



O projeto completo de exemplo, com os codigos está armazenado no Google Code (VB.NET e C#).