Criando um GridView via código

Hoje ajudei uma pessoa que precisava ter um GridView criado de forma dinâmica. É uma tarefa simples, no entanto o problema estava em inserir um controle DropDownlist dentro do TemplateField.

O que facilitou foi utilizar uma classe que herda de ITemplate:

public class GridViewTemplate : ITemplate
{
}

No aspx foi inserido apenas um button que faz a carga do gridview:

<body>
    <form id="form1" runat="server">
    <div>
    <asp:Button ID="btnCarregar" runat="server"
     onclick="btnCarregar_Click" Text="Carregar" />
     <br />
        <asp:Panel ID="Panel1" runat="server">
        </asp:Panel>
    </div>
    </form>
</body>

A idéia foi mostrar um GridView com informações sobre cursos: Código do Curso, Nome do curso e O status (concluído, em andamento ou encerrado).

Para isto comecei criando duas classes (Status e Curso):

public class Status
{
    public int CODIGO { get; set; }
    public string DESC { get; set; }

    public static List<Status> GetStatus()
    {
        List<Status> lista = new List<Status>();
        lista.Add(new Status() { CODIGO = 1, DESC = "Concluído" });
        lista.Add(new Status() { CODIGO = 2, DESC = "Em andamento" });
        lista.Add(new Status() { CODIGO = 3, DESC = "Encerrado" });

        return lista;
    }
}
public class Curso
{
    public int CODIGO { get; set; }
    public string DESC { get; set; }

    public static List<Curso> GetCursos()
    {
        List<Curso> lista = new List<Curso>();
        lista.Add(new Curso() { CODIGO = 1, DESC = "Contabilidade" });
        lista.Add(new Curso() { CODIGO = 2, DESC = "Informática" });
        lista.Add(new Curso() { CODIGO = 3, DESC = "Letras" });

        return lista;
    }
}

Em seguida realizar a carga gridview:

void BindGrid()
{
	GridView grv = new GridView();
	grv.AutoGenerateColumns = false;
	grv.ID = "grvExemplo";

	BoundField columnCodigo = new BoundField();
	columnCodigo.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
	columnCodigo.HeaderText = "Codigo";
	columnCodigo.DataField = "CODIGO";
	grv.Columns.Add(columnCodigo);

	BoundField columnCurso = new BoundField();
	columnCurso.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
	columnCurso.HeaderText = "Curso";
	columnCurso.DataField = "DESC";
	grv.Columns.Add(columnCurso);

	TemplateField templateEmail = new TemplateField();
	templateEmail.ItemTemplate = new GridViewTemplate(DataControlRowType.DataRow, "");
	templateEmail.HeaderTemplate = new GridViewTemplate(DataControlRowType.Header, "");
	grv.Columns.Add(templateEmail);

	List<Curso> cursos = Curso.GetCursos();
	grv.DataSource = cursos;
	grv.DataBind();

	Panel1.Controls.Add(grv);
}

O controle DropDownlist foi criado no evento InstantiateIn da classe GridViewTemplate:

public class GridViewTemplate : ITemplate
{
    private DataControlRowType templateType;
    private string columnName;

    public GridViewTemplate(DataControlRowType type, string colname)
    {
        templateType = type;
        columnName = colname;
    }

    public void InstantiateIn(System.Web.UI.Control container)
    {
        if (templateType == DataControlRowType.DataRow)
        {
            List<Status> status = Status.GetStatus();
            DropDownList ddl = new DropDownList();
            ddl.ID = "ddlStatus";
            ddl.DataTextField = "DESC";
            ddl.DataValueField = "CODIGO";
            ddl.DataSource = status;
            ddl.DataBind();
            container.Controls.Add(ddl);
        }
    }
}

Resultado:

Referências:
ITemplate Interface
http://msdn.microsoft.com/en-us/library/system.web.ui.itemplate.aspx

Método ITemplate.InstantiateIn
http://msdn.microsoft.com/pt-br/library/system.web.ui.itemplate.instantiatein%28v=vs.90%29.aspx

Programmatically adding template field in ASP.NET GridView problem
http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_23171849.html

Linq e tipos genéricos (generic types)

Os tipos genéricos foram adicionados ao framework 2.0 e estão dentro do namespace System.Collections.Generic.

Uma consulta LINQ é baseada em generic types (tipos genéricos). Para utilizar não é necessário ter um conhecimento profundo sobre tipos genéricos (generic types). No entanto, é importante compreender dois conceitos básicos:

1. Quando você cria uma instância de uma classe de coleção genérica, como List<T>, você substitui o “T” com o tipo de objeto que a lista irá trabalhar. Por exemplo, uma lista de strings é expresso como List<string>, e uma lista de objetos Usuario é expresso como List< Usuario >:

//Lista genérica de string
List<string> listaDeString = new List<string>();

//Lista genérica de objetos do tipo Usuario
List<Usuario> listaDeUsuario = new List<Usuario>();

Uma lista (List) genérica é fortemente tipado e oferece muitas vantagens sobre coleções que armazenam seus elementos como Object. Se você tentar adicionar um Usuario a um List<string>, você obterá um erro (argumento inválido) em tempo de compilação, pois o objeto esperado é do tipo string:

2. É a interface IEnumerable<T> que permite que classes de coleções genérica possam ser enumerados usando a instrução foreach.

IEnumerable<T> como variável ​​em consultas LINQ

Variáveis ​​de consulta LINQ são escritas como IEnumerable<T> ou um tipo derivado, como IQueryable<T>. Quando você vê uma variável de consulta que é escrita como IEnumerable<Usuario>, isso significa apenas que a consulta, quando ela é executada, irá produzir uma seqüência de zero ou mais objetos do tipo Usuario:

IEnumerable<Usuario> usuariosAtivosQuery = from u in usuarios
                                            where u.ATIVO == true
                                            select u;
foreach (Usuario user in usuariosAtivosQuery)
{
    Console.WriteLine("Nome: {0}", user.NOME);
}

Permitindo que o compilador resolva o tipo em tempo de execução

Você pode evitar escrever o tipo genérico usando a palavra-chave var. A palavra-chave var instrui o compilador para inferir o tipo de uma variável de consulta ao olhar para a fonte de dados especificado na cláusula from. O exemplo a seguir produz o mesmo código compilado como o exemplo anterior:

var usuariosAtivosQuery = from u in usuarios
                                            where u.ATIVO == true
                                            select u;
foreach (Usuario user in usuariosAtivosQuery)
{
    Console.WriteLine("Nome: {0}", user.NOME);
}

A palavra-chave var é útil quando o tipo da variável é óbvio ou quando ele não é tão importante para especificar explicitamente tipos genéricos, tais como aqueles que são produzidos por consultas.

O objeto utilizado no exemplo foi:

class Usuario
{
    public int CODIGO { get; set; }
    public string NOME { get; set; }
    public bool ATIVO { get; set; }
}

Referência:
LINQ and Generic Types (C#)
http://msdn.microsoft.com/en-us/library/bb546142.aspx

Codificando Night Week

Durante uma semana, todas as noites, o Codificando .Net apresentará temas relacionados ao Desenvolvimento Web utilizando ferramenta online de transmissão de evento (web cast).

Os links diários das salas online serão disponibilizados nesta página no dia do evento. A participação será gratuita.

Segunda 30/01: Desenvolvimento WEB

* 20:30 hs – Cleber: Entendendo requisições HTTP, funcionamento da internet, etc
* 21:30 hs – Cucharro: HTML 5 e CSS 3, o que muda na nossa vida?
* 22:00 hs – Andrey: Arquitetura de verdade em projetos ASP.NET
* 22:30 hs – Alexandre: Dicas rápidas que pode melhorar sua aplicação ASP.NET

Terça 31/01: ASP.NET Web Forms

* 20:30 hs – Andrey: Principais recursos do Web Forms 4
* 21:30 hs – Alexandre: Obtendo melhores resultados de performance em aplicações Web Forms 4
* 22:00 hs – Palestra 3:à definir

Quarta 1/2: ASP.NET MVC

* 20:30 hs – Cleber: Novidades do MVC 3
* 21:30 hs – Rodolfo: Boas práticas de ASP.NET MVC
* 22:00 hs – Alexandre: Migrando de ASP.NET Web Forms para ASP.NET MVC
* 22:30 hs – Andrey: à definir

Quinta 2/2: Fora da caixa

* 20:30 hs – Cucharro: KnockoutJS
* 21:00 hs – Alexandre: Trabalhando com memCached e ASP.NET
* 21:30 hs – Cleber: labjs, jquery e outras bibliotecas JS para resolver nossos problemas
* 22:00 hs – Rodolfo: Lucene.Net, criando resultados de buscas mais eficientes

Sexta 3/2: infra

* 20:30 hs – Cleber: o que precisamos saber de IIS [como identificar problemas de aplicação no iis]
* 21:30 hs – Alexandre: CDN, Núvem, proxy… um pouco de como funciona a internet
* 22:00 hs – Rodolfo: Entregando arquivos estáticos com proxy reverso no nginx
http://comunidade.codificando.net/page/codificando-night-week

Revisão das metas pessoais de 2011

- Ler 2 Livros a cada dois meses
Falta pouco para alcançar a meta (apenas 1 livro). As várias atividades que aparecem acaba dificultando coisas deste tipo, pois o tempo é reduzido.
- Passar no Exame 70-561 (Acesso a dados no Framework 3.5)
Passei na primeira. A próxima é a 70-562.
- Contribuir no fórum MSDN
Já tem 4 meses que todos os dias respondo nos fóruns de ASP.NET, C#, VB.NET, Visual Studio etc. O total de pontos de reconhecimento já chegou a 7.925:

Como visualizar o T-SQL gerado pelo Linq To SQL ou Entity Framework na consulta Linq

Linq To Sql

Basta acessar a propriedade CommandText do objeto DataContext:

Saída:

Entity Framework

No EF é preciso fazer um cast na query para um objeto do tipo ObjectQuery (System.Data.Objects) e com isto utilizar o método .ToTraceString() para visualizar a query gerada:

Saída:

Quando já temos o tipo definido o cast não se faz necessário:

Resultado:

Referência(s):

ObjectQuery.ToTraceString Method
http://msdn.microsoft.com/en-us/library/system.data.objects.objectquery.totracestring.aspx

How to see the T-SQL Query LINQ to SQL or Entity Framework is making out of your LINQ Query ?
http://geekswithblogs.net/claeyskurt/archive/2009/04/15/131232.aspx

.NET – ADO.NET Entity Framework & LINQ to Entities – part 2
http://www.scip.be/index.php?Page=ArticlesNET13

TDC 2011. Está chegando a hora.

O TDC (The Developers Conference) 2011 vai acontecer sábado agora, em Goiânia. Ainda dá tempo de fazer a inscrição.

A grade do evento está “recheada” dos mais diversos assuntos:

Eu, como desenvolvedor .NET vou assistir a trilha de .NET no sábado. Quero ver a palestra “Desenvolvendo aplicativos para windows phone”.

Editando a célula no DataGridView

Apensar de não ser “expert” em windows forms, fiz uma pequena demonstração de como alterar uma linha no DataGridView. O exemplo foi feito com o objetivo de contribuir para mais uma thread no fórum MSDN. A quem interessar Eu criei ainda um video mostrando o funcionamento. É simples e útil. Com certeza existe N maneiras de se fazer a mesma coisa. Neste caso Eu utilizei o evento CellEndEdit.

Para testar basta criar a tabela (o script está dentro da pasta “script” e alterar a string de conexão no código.

Código Fonte : exemplo.rar

Para baixar o video basta ciclar na imagem abaixo.

Chamar o mesmo evento com controles diferentes

Ontem um colega do fórum MSDN pediu um help sobre a manipulação de eventos de um controle Button criado em tempo de execução. Após responder me lembrei de que uma outra pessoa da lista .NET – BR havia feito uma pergunta que consistia em: como disparar o mesmo evento de um botão através de outro??

Bom, para isso basta criar um EventHandler e apontar para o evento “Click” os dois controles:

Informar o EventHandler que deve ser “disparado” no click do botão:

protected void Page_Load(object sender, EventArgs e)
{
   btnB.Click += new EventHandler(EventoQualquer);
   btnA.Click += new EventHandler(EventoQualquer);
}

Handler:

protected void EventoQualquer(object sender, EventArgs e)
{
   Button btn = (Button)sender;

   if(btn.ID == "btnA")
       txtData.Text = "button A";
   else
       txtData.Text = "button B";
}

Problema resolvido.

Agora vamos imaginar que além de um button precisamos chamar o mesmo evento com um controle do tipo dropdownlist. E agora? Basta seguir a mesma idéia. É claro que que este controle não possui o evento “Click” e sim SelectedIndexChanged . Então além de setar o AutoPostBack para True, vamos informar o EventHandler que deve ser disparado quando uma opção for selecionada no controle DropDownlist:

ddlTeste.SelectedIndexChanged += new EventHandler(EventoQualquer);

Outra alteração que deve ser feita é que tipo de controle foi acionado:

protected void EventoQualquer(object sender, EventArgs e)
{
   if(sender.GetType().Name.Equals("DropDownList"))
   {
      DropDownList ddl = (DropDownList)sender;
      txtData.Text = ddl.SelectedValue;
   }
   else
       if(sender.GetType().Name.Equals("Button"))
       {
          Button btn = (Button)sender;
          if (btn.ID == "btnA";)
             txtData.Text = "button A";
          else
             txtData.Text = "button B";
       }
}

Agora o código completo:

protected void Page_Load(object sender, EventArgs e)
{
    btnB.Click += new EventHandler(EventoQualquer);
    btnA.Click += new EventHandler(EventoQualquer);
    ddlTeste.SelectedIndexChanged += new EventHandler(EventoQualquer);
}

protected void EventoQualquer(object sender, EventArgs e)
{
  if (sender.GetType().Name.Equals("DropDownList"))
  {
     DropDownList ddl = (DropDownList)sender;
     txtData.Text = ddl.SelectedValue;
  }
  else
      if (sender.GetType().Name.Equals("Button"))
      {
          Button btn = (Button)sender;
          if (btn.ID == "btnA")
             txtData.Text = "button A";
          else
             txtData.Text = "button B";
      }
}

Páginas de Erro no ASP.NET

Recentemente encontrei uma opção que nunca vi sendo utilizada. Trata-se do redirecionamento para uma página de erro personalizada. Calma, não estou falando da página padrão que normalmente é configurada no web.config .

O geral que Eu conhecia e utilizo é colocar a url da página na opção “defaultRedirect” da tag “customErros” no web.config, algo mais ou menos assim:

 <customErrors mode="On" defaultRedirect="~/ErroGeral.aspx"></customErrors>
 

Com isso qualquer erro que acontecer na aplicação, será apresentado para o usuário a pagina ErroGeral.aspx .

No entanto vamos imaginar que para uma página em específico o redirecionamento deve ser feito para outra tela totalmente personalizada. É aí que vem o “pulo do gato”.  Lá no source da sua página .aspx basta adicionar a tag ErroPage=”SuaPaginaDeErroPersonalizada”:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebSite._Default" ErrorPage="~/Erro.aspx" %>

Pronto. Toda vez que ocorrer uma exceção nesta página, será apresentado para o usuário a página personalida.

Passei na prova 70-561

Mais uma meta comprida. Fui aprovado no exame 70-561.

Agora o próximo passo é a prova 70-562.  Ainda este ano quero conseguir a credencial MCPD ASP.NET Web Application.