Páginas

Mostrando postagens com marcador models. Mostrar todas as postagens
Mostrando postagens com marcador models. Mostrar todas as postagens

segunda-feira, 21 de maio de 2012

Gerando uma grid agrupada com Ext JS

Para manipulação do DOM eu tenho total preferencia pelo jquery, ja para geração de grids e afins o framework Ext JS, realmente é insuperável, a curva de aprendizagem dele, não é das melhores e faltam exemplos praticos na internet sobre a geração pratica de grids (pelo menos ao meu ponto de vista), porem uma vez dominado, se torna uma ferramenta tão poderosa, que você chega se perguntar como pode viver sem isso ate hoje.
Hoje vou postar sobre como gerar uma grid com registros agrupados, e botões de ação.
Inicialmente quero frisar que o framework Ext Js é pago, sendo liberado apenas para projetos open source, porem o custo x beneficio dele é muito bom mesmo.
Primeiro baixem o framework no site Sencha.
Uma vez salvo no computador local, vamos instala-lo:
Por motivos de organização eu optei por colocar os .js na pasta Content > Ext, e as imagens em resources > images como mostra na figura abaixo
Na pasta Ext tem todos os arquivos java do framework enquanto na images tem as imagens do framework.
Abra um projeto de nome de sua preferencia e vamos instalar o framework nele.

<link rel="stylesheet" href="@Url.Content("~/Content/ext/css/ext-all.css")" type="text/css" media="screen" />
<script type="text/javascript" src="@Url.Content("~/Content/ext/js/ext-all.js")"></script>

Aqui existem algumas observações:
Em muitos exemplos pela internet afora eu vejo as pessoas referenciando seus arquivos de forma manual, eu nao vejo isso como certo, porem eu gosto de desenvolver localmente e fazer o deploy de arquivos apenas quando necessario mesmo, entao nesse caso, para poder ter mais produtividade eu uso o "URL.Content" que "descobre" a estrutura de pasta que se encontra e ja a usa de forma correta.
Voltando ao sssunto principal, basta referenciarmos esses dois arquivos que o framework ja estara instalado.
No Mvc, o correto é gerar models "gordas", com todo o processamento entao em uma interface eu criei um content result como se segue:

        public ContentResult XmlUsuariosGrupos(string Conf)
        {
            BancoEntities BD = new BancoEntities();

            //reconstruindo o helper para dar o action no link-------------------------------------------------------------------------------
            HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
            UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));
            //-------------------------------------------------------------------------------------------------------------------------------


            var Listagem = (from usu_grupos in BD.usu_grupos
                            from usuarios in BD.usuarios
                            where
                              usuarios.CodGrupo == usu_grupos.Usu_Gru_Cod &&
                              usu_grupos.Conf_Codigo == Conf
                            select new
                            {
                                usu_grupos.Usu_Gru_Nome,
                                usuarios.Nome,
                                usuarios.Sobrenome,
                                usuarios.CodUsuario,
                                usuarios.CodGrupo
                            });

            XElement matches = new XElement("Grupos");
            XElement match = null;
            XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), matches);

            foreach (var item in Listagem)
            {
                match = new XElement("Agrupamento");
                match.Add(new XElement("id", item.CodUsuario));
                match.Add(new XElement("Nome", item.Nome + " " + item.Sobrenome));
                match.Add(new XElement("Grupo", item.Usu_Gru_Nome));
                match.Add(new XElement("Acoes", "<a href='" + urlHelper.Action("EditaDireitosEspeciais", "Iniciais", new { id = item.CodUsuario, CodGrupo = item.CodGrupo } ) + "'>Gerenciar Direitos Especiais</a>"));
                matches.Add(match);
            }
            ContentResult ret = new ContentResult();
            ret.ContentType = "text/xml";
            ret.Content = doc.ToString();
            return ret;
        }

Com isso geramos um xml satisfatorio para o Framework, vamos prestar atenção em um detalhe: no contexto de model o helper do action link nao funciona, sendo que é necessário reconstruir o mesmo dentro do ContentResult para o mesmo poder ser utilizado, afinal por mais utilidade que se tenha uma listagem, ela não passa apenas de uma listagem, e as vezes precisamos de botões de ação, para edição de usuarios, CRUDS em geral, etc.
Na nossa view eu coloquei o java da seguinte forma:

<script type="text/javascript">

    Ext.Loader.setConfig({
        enabled: true
    });
    Ext.Loader.setPath('Ext.ux', '../ux');

    Ext.require([
    'Ext.grid.*',
    'Ext.data.*',
]);

    Ext.onReady(function () {
        Ext.define('Book', {
            extend: 'Ext.data.Model',
            fields: [
            {name: 'Nome', mapping: 'Nome' },
            'Grupo', 'Acoes'
        ]
        });

        var store = Ext.create('Ext.data.Store', {
            model: 'Book',
            autoLoad: true,
            //inserindo propriedades de agrupamento------------
            groupField: 'Grupo',
            //-------------------------------------------------
            proxy: {
                type: 'ajax',
                url: "@Url.Content("~/Listagem/_ListaGruposUsuariosXml/")?Conf=@ViewBag.Conf",
                reader: {
                    type: 'xml',
                    record: 'Agrupamento',
                    idProperty: 'id'
                }
            }
        });

        var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
            groupHeaderTpl: 'Nome do Grupo: {name} ({rows.length} Usuários Cadastrado{[values.rows.length > 1 ? "s" : ""]})',
            hideGroupedHeader: false,
            startCollapsed: true
        });

        // create the grid
        var grid = Ext.create('Ext.grid.Panel', {
            store: store,
            columns: [
            { text: "Nome", width: 250, dataIndex: 'Nome', sortable: true },
            { text: "Nome do Grupo de usuários", width: 250, dataIndex: 'Grupo', sortable: true },
            { text: "Ações Possiveis", width: 250, dataIndex: 'Acoes', sortable: false },
        ],

           //funcoes extras---------------------------------------------------------------------
            collapsible: true,
            animCollapse: true,
            iconCls: 'icon-grid',
            frame: true,
            resizable: true,
            title: "Grupos de usuários",
           //----------------------------------------------------------------------------------

           //aqui começa o agrupamento----------------------------------------------------------
            features: [groupingFeature],
           //-----------------------------------------------------------------------------------

            renderTo: 'Grid',
            width: 900,
            height: 700
        });
    });

</script>
Bom primeiramente, devo me desculpar pois eu fiz muito "em cima do exemplo" do site do Ext JS, detesto manter os nomes das variaveis, mas como o proposito aqui é apenas um exemplo entao acabei deixando.
Alguns detalhes merecem um pouco de atenção como a linha:

Ext.Loader.setPath('Ext.ux', '../ux');

Aqui o framework diz onde estao seus outros arquivos de apoio e o motivo que eu deixei a organização dele sem mexer, apenas para melhorar a compreensão.

na linha

url: "@Url.Content("~/Listagem/_ListaGruposUsuariosXml/")?Conf=@ViewBag.Conf",

chamamos o ajax que carregara a grid com o xml de dados, observe o uso do helper Url.Content .

o Xml que eu gerei ficou mais ou menos assim

<Grupos>
  <Agrupamento>
    <id>77</id>
    <Nome>Theo Teste</Nome>
    <Grupo>Grupo Limitado</Grupo>
    <Acoes>&lt;a href='/Iniciais/EditaDireitos/77?Grupo=139'&gt;Gerenciar Direitos Especiais&lt;/a&gt;</Acoes>
  </Agrupamento>
</Grupos>
 
 
nas linhas
reader: {          
            type: 'xml',          
            record: 'Agrupamento',          
            idProperty: 'id'         
            }
Indicamos que sera enviado um xml, ja que o framework suporta outros formatos, informamos que as linhas estao na chave Agrupamento, e o Id de cada registro é o id


nas linhas:
    Ext.onReady(function () {
        Ext.define('Book', {
            extend: 'Ext.data.Model',
            fields: [
            {name: 'Nome', mapping: 'Nome' },
            'Grupo', 'Acoes'
        ]
Definimos o nome das colunas, preste atenção que somente a primeira precisa ser mapeada, sendo que as outras ja vem na sequencia apenas com os nomes


nas linhas:
        var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
            groupHeaderTpl: 'Nome do Grupo: {name} ({rows.length} Usuários Cadastrados{[values.rows.length > 1 ? "s" : ""]})',
            hideGroupedHeader: false,
            startCollapsed: true
        });

criamos a grid com o agrupamento sendo que antes do nome do agrupamento vira a string "Nome do Grupo:" e o proprio framework faz a conta de linhas em
({rows.length} Usuários Cadastrados{[values.rows.length > 1 ? "s" : ""]})
para saber quantos usuarios estao cadastrados nesse agrupamento.

na linha:

startCollapsed: true

diz que os registros ja vem "fechados" mostrando apenas os agrupamentos.

nas linhas:
        var grid = Ext.create('Ext.grid.Panel', {
            store: store,
            columns: [
            { text: "Nome", width: 250, dataIndex: 'Nome', sortable: true },
            { text: "Nome do Grupo de usuários", width: 250, dataIndex: 'Grupo', sortable: true },
            { text: "Ações Possiveis", width: 250, dataIndex: 'Acoes', sortable: false },
        ],
Informamos o framework que a chave "Nome" no Xml linka com a Coluna "Nome", sua largura em px, e se ele pode ser "organizavel" ou seja se vc pode clicar na coluna e a grid se rearranjar em ordem crescente ou decrescente com base na coluna selecionada, as outras linhas seguem o mesmo padrão.

nas linhas:

           //funcoes extras---------------------------------------------------------------------
            collapsible: true,
            animCollapse: true,
            iconCls: 'icon-grid',
            frame: true,
            resizable: true,
            title: "Grupos de usuários",
           //----------------------------------------------------------------------------------

temos as funções extras da grid, autoexplicaveis.

na linha:

           //aqui começa o agrupamento----------------------------------------------------------
            features: [groupingFeature],
           //-----------------------------------------------------------------------------------

aplicamos as preferencias ja citadas na grid

nas linhas:

            renderTo: 'Grid',
            width: 900,
            height: 700

informamos que o elemento que recebera a grid tem o Id de "Grid", sua largura e altura, no meu caso foi uma div com id de "Grid"

espero ter sido de utilidade, e em caso de duvidas ou afins, por favor me enviem um email ou comentem a duvida porque eu ficarei feliz em ajudar...

sexta-feira, 18 de maio de 2012

Conectando o MySql no Visual Studio 2010

Quando eu nao sabia direito como funcionava, eu procurei muito na internet e nao achei nada que fosse realmente esclarecedor para mim, tentei por muito tempo diversas formas diferentes, mas nada dava certo satisfatoriamente.
Primeiro vamos as considerações:
Nao adianta querer trabalhar com o MySql no Visual Studio 2010 express, ele simplesmente nao tem suporte.
(Mas como assim? eu conheço fulano, ciclano e beltrano que conseguiu) Explicando, ele nao tem um suporte facil, porem se voce ja dominar a linguagem você consegue sim (todo o segredo esta no web.config), porem com muitas limitações(code first pode esquecer).
O melhor suporte que eu encontrei foi no Visual Studio 2010 ultimate que é o que eu vou descrever aqui.
Me parece, não sei se estou certo, a Microsoft não tem interesse em tornar o MySql nativo do Visual Studio, nao sei se no 2011 ja mudou, mas acredito que não.
Entao temos que baixar o conector do MySql, nao vou colocar o link direto aqui, esse foi um erro que encontrei em diversos sites que eu consultei inicialmente para tentar entender e sempre ficava a duvida se as instruções eram para uma versão especifica ou era mais generico, basta entrar no site do MySql, e baixar a ultima versão do conector que sempre sera necessario, por diversos motivos, entre eles, correção de bugs, mais rendimento e etc...
Uma vez baixado e instalado, reinicie o Visual Studio e mãos a obra.
Modele o banco de dados externamente já que o code first não esta disponivel (se alguem conseguiu comente que eu estudo o modo e coloco um post so sobre isso aqui), e no projeto criado clique com o botao direito na pasta models(para uma melhor organização) selecione "Add" e na aba seguinte "New Item" ira aparecer uma janela mais ou menos como a da imagem abaixo, basta selecionar em "Installed Templates" a opção "Data" para filtrar as opções de dados e logo após "ADO.NET Entity Data Model", como na imagem abaixo:
Primeiro passo
O nome que eu dei é somente um exemplo, pode ser desconsiderado (ja vi programador que ate hoje se utiliza de nomes propostas por cursos, então eu tento nao prender ninguem no meu sistema de nomenclatura).
Quando clicar em ok uma janela como a de baixo ira aparecer:
Segundo Passo
Escolha o "Generate from database", pois o outro gera um sql que não é inteiramente compativel com o MySql, pelo menos ate a versão que eu testei, entao recomendo usar ele
Clicando em "Next" a proxima tela ira aparecer:
Eu numerei os passos, no circundado numero 1 voce podera escolher entre outras conexoes ja prontas entre todos os bancos de dados que ja foram selecionado, aqui iremos escolher "New Connection"
Ira aparecer uma tela como a seguir:


Aqui finalmente iremos "Desenterrar" o nosso MySql Connector, em "Data Source" provavelmente ira figurar outra conexão a outro tipo de banco de dados, clique em Change e selecione "MySql DataBase (Mysql Data Provider)" (se essa opção não estiver disponivel nesse passo, é porque seu conector nao esta instalado corretamente, ou algum outro problema ocorreu escreva sua duvida nos posts que eu tento resolver junto.) Em "Server Name", coloque o endereço de acesso ao banco de dados (ip, site e afins), em "User Name" o nome de usuário e em "Password" sua senha de acesso ao seu banco de dados, opcionalmente marque "Save my password" eu uso marcado, e nesse post vou considerar que você marcou tbm.
Feito tudo isso o proprio conector ira entrar no banco de dados selecionado e você podera escolher o banco de dados que ira usar.
Se tudo deu certo ate agora provavelmente voltara a tela anterior novamente.
Selecione "Yes, include include the sensitive data in connections string", isso fara com que nao seja necessario reescrever a connexction a cada conexao ao banco sendo que a mesma ficara inclusa no web.config.
"Tique"  a caixa logo acima do numero 2 para ele ficar habilitado e nomeie a sua conexão ao banco de dados.
Se tudo deu certo ate agora o entity ira entrar no seu banco de dados e mapea-lo, fornecendo uma tela como a seguir:
onde todas as tabelas ja estarao mapeadas e prontas para serem usadas.
Em model Namespace nomeie o seu model e pronto!
Seu projeto ja estara conectado no banco de dados MySql.
Agradeço a atenção de todos.
Esse post foi pedido pelo Arthur Ciurilli por pedido de Marcos Bazzo.
Espero ter ajudado e se alguem quizer alguma postagem em especial é so pedir no meu email que esta aqui no site mesmo que eu faço o post com muita satisfação.


domingo, 6 de maio de 2012

Função do Controller

Eu vejo muito por aí as pessoas colocando muitas funções no controller e eu mesmo até um tempo atrás colocava muito processamento num controller, porém um amigo da lista .Net-Br me indicou uma forma melhor para organizar o código, e hoje em dia percebo as vantagens dessa organização.
No modelo MVC de programação o controller é responsável pelo direcionamento de actions, rotas, pedido de processamento para as models, e pouco processamento efetivo, tais como um try catch ou talvez um if, mas o processamento mais pesado fica em interfaces, nas models mais dedicadas a isso, note que não estou dizendo que deveria ficar na mesma models que trata do banco de dados mas numa em separado, possibilitando que determinadas classes sejam inclusive reutilizados em outros setores do sistema em desenvolvimento, eu pessoalmente crio uma pasta com o nome do controller que ela será utilizada, sem a extensão controller, claro.
Na próxima postagem, pretendo colocar alguns exemplos dessa organização.
Até mais...