Marcos Natan developer

Olá galera!! I’m back!!! Hoje vou mostrar como chamar uma das interações do javascript object model do Sharepoint 2010: Notifications. Qualquer página(Sitepage, Application page) que esteja no contexto do sharepoint tem acesso a algumas bibliotecas javascript carregadas pelo próprio sharepoint. Essas bibliotecas proporcionam boas interações com o usuário em termos de interface gráfica e usabilidade. Nossa missão de hoje é chamar um script que acesse uma dessas bibliotecas a partir do code behind. A idéia de execução de scripts a partir do code behind é muito conveniente, pois possibilita a aplicação de regras de negócio ao contexto. Pois vamos lá.

Primeiramente abra o vs(visual studio), Iniciar > Todos Programas > Microsoft Visual Studio 2010 > Microsoft Visual Studio 2010. Depois é necessário que criemos um novo projeto sharepoint vazio que conterá uma webpart que servirá como exemplo. Vá em File > New > Project (meu vs está em inglês, mas nada que uma tradução literal não possa resolver). Na janela de New Project, no painel lateral esquerdo, expanda a aba que representa a linguagem de sua preferência(no meu caso c#, sintam-se livres para adaptar para qualquer outra linguagem suportada), depois expanda a aba Sharepoint e em seguida a aba 2010. Selecione o template, no painel central, Empty Sharepoint Project e preencha o campo Name como JavascriptObjectModelDemo. Ok, temos um ponto de partida.

Empty Sharepoint Project

Abra a Solution Explorer, clique com o botão direito do mouse do nome do projeto(JavascriptObjectModelDemo, abaixo de Solution JavascriptObjectModelDemo) e selecione Add > New Folder. Renomeie a pasta para WebParts. Repita o processo e crie uma pasta chamada Extensoes. Agora precisamos adicionar a webpart, para isso clique com o botão direito na pasta WebParts e selecione Add > New Item. Na janela Add New Item, selecione Visual Web Part e preencha o campo Name com WpDemo(Aconselho a usar prefixos, pois sempre facilitam a localização de arquivos em uma solução). No código que abrirá, abra a ToolBox e arraste um TextBox e um Button (fique à vontade para organizar o layout) e dê-lhes os respectivos ID’s txtNome e btnEnviar.

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
    Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
    Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WpDemoUserControl.ascx.cs"
    Inherits="JavascriptObjectModelDemo.WebParts.WpDemo.WpDemoUserControl" %>
<label for="txtNome">
    Nome:</label><br />
<asp:TextBox runat="server" ID="txtNome" CssClass="caixaDeTexto" EnableViewState="false" /><br />
<asp:Button runat="server" ID="btnEnviarNome" Text="Enviar" CssClass="botao" OnClick="btnEnviarNome_Click" />

Ok, vamos agora criar a classe que conterá as extensões.
Adicione uma classe chamada DemoSpUI na pasta Extensoes. Cole o código seguinte no arquivo DemoSpUI.cs:

namespace JavascriptObjectModelDemo.Extensions
{
    public static class DemoSpUI
    {
        #region Propriedades

        private const string Notificacao = "MostrarNotificacao";

        #endregion

        #region Métodos

        public static void MostrarNotificacao(this Page pagina, string texto, bool persistirNotificacao)
        {
            // Buscando o ClientScriptManager
            var scriptManager = pagina.ClientScript;

            // Verificando se o script já existe na página
            if (!scriptManager.IsClientScriptBlockRegistered(Notificacao))
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("SP.SOD.executeOrDelayUntilScriptLoaded(mostrarNotificacao, \"sp.js\");");
                sb.AppendFormat("function mostrarNotificacao(){{ {0} }}", string.Format("SP.UI.Notify.addNotification(\"{0}\", {1})", texto, persistirNotificacao.ToString().ToLower()));
                scriptManager.RegisterClientScriptBlock(pagina.GetType(), Notificacao, sb.ToString(), true);
            }
        }
        #endregion
    }
}

O que esse código faz é adicionar um método de extensão (MostrarNotificação) à classe Page (System.Web.UI.Page). Esse método, via ScriptManager, registra um bloco de código javascript, que utiliza o Javascript Object Model para exibir uma notificação, para ser executado na página. Agora abra novamente a WebPart (WpDemoUserControl.ascx) e, usando o modo Designer, dê um duplo clique no botão arrastado para tela. Isso gerará o event handler do evento de clique do botão. Adicione o seguinte using no topo do arquivo:

using JavascriptObjectModelDemo.Extensoes; // Necessário para podermos invocar nosso método de extensão na classe Page

Agora adicione o seguinte código dentro do método gerado pelo Visual Studio ()

protected void btnEnviar_Click(object sender, EventArgs e)
        {
            // Registrar script para ser executado na página
            if (!string.IsNullOrEmpty(txtNome.Text))
            {
                this.Page.MostrarNotificacao("Olá " + txtNome.Text + " seja bem-vindo(a)!", false);
            }
        }

Agora dê deploy da solução e adicione a webpart criada em uma WebPartPage (default.aspx). Digite qualquer coisa na caixa de texto e clique o botão Enviar. Eis o resultado:

Notificação via CodeBehind


Bom, é isso!! Até a próxima

Olá pessoas!! No post de hoje vou mostrar uma, dentre as várias possíveis, solução para uma tarefa que frequentemente temos que fazer: criar máscaras de formatação javascript para campos de formulário. Neste exemplo, criarei uma máscara para cpf e outra para data. Para começar, vamos definir uma página html que contenha dois elementos <input> de exemplo.

<!DOCTYPE html>
<html>
<head>
<title>Máscaras javascript</title>
</head>
<body>
Cpf: <input type="text" id="txtCpf" maxlength="14" /><br/>
Data de nascimento: <input type="text" id="txtData" maxlength="10" />
</body>
</html>

Agora precisamos manipular o evento OnKeyPress dos elementos <input> para que possamos controlar aquilo que foi digitado no <input>. Para isso, vamos criar duas funções: mascaraData e mascaraCpf, e em seguida dar o
Inline Bind passando o objeto event por meio do atributo onkeypress=””
. E nelas faremos toda a lógica pertinente a cada tipo de campo. Segue o código das duas funções javascript:

// Função que aplica uma máscara de formato à Data
function mascaraData(evento)
{
	var origem;
	var txtOrigem;
	var key;
	if(window.event)
	{
		key = evento.keyCode;
		if(key >= 48 && key <= 57)
		{
			origem = evento.srcElement;
			txtOrigem = origem.value;
			if(txtOrigem.length == 2 || txtOrigem.length == 5 )
			{
				txtOrigem += "/";
				origem.value = txtOrigem ;
			}
		}else
		{
			event.returnValue = false;
		}	
	}
	else
	{
		key = evento.which;
		if(key >= 48 && key <= 57)
		{
			origem = evento.target;
			txtOrigem = origem.value;
			if(txtOrigem.length == 2 || txtOrigem.length == 5 )
			{
				txtOrigem += "/";
				origem.value = txtOrigem ;
			}
		}else
		{
			if(key != 8 && key != 0)
			{
				evento.preventDefault();
			}
		}
	}
}

// Função que aplica uma máscara de formato ao Cpf
function mascaraCpf(evento)
{
	var origem;
	var txtOrigem;
	var key;
	if(window.event)
	{
		key = evento.keyCode;
		if(key >= 48 && key <= 57)
		{
			origem = evento.srcElement;
			txtOrigem = origem.value;
			if(txtOrigem.length == 3 || txtOrigem.length == 7 )
			{
				txtOrigem += ".";
				origem.value = txtOrigem ;
			}
			if(txtOrigem.length == 11)
			{
				txtOrigem += "-";
				origem.value = txtOrigem ;
			}
		}else
		{
			event.returnValue = false;
		}	
	}
	else
	{
		key = evento.which;
		if(key >= 48 && key <= 57)
		{
			origem = evento.target;
			txtOrigem = origem.value;
			if(txtOrigem.length == 3 || txtOrigem.length == 7 )
			{
				txtOrigem += ".";
				origem.value = txtOrigem ;
			}
			if(txtOrigem.length == 11)
			{
				txtOrigem += "-";
				origem.value = txtOrigem ;
			}
		}else
		{
			if(key != 8 && key != 0)
			{
				evento.preventDefault();
			}
		}
	}
	
}

Vamos analisar o código acima. A condição:

if(window.event)
{
}

verifica se o browser suporta a propriedade event do objeto window (ou seja, verifica se o browser é o IE). Se sim, para buscarmos o elemento que originou o evento usaremos a propriedade srcElement do objeto event. E para buscar o caractere digitado usamos a propriedade keyCode. Caso não seja o IE, usaremos as propriedades target e which para buscar o elemento que originou o evento e o caractere digitado, respectivamente. A condição:

if(key >= 48 && key <= 57)
{
}

verifica se o caractere digitado é um dígito (0..9) (perdoe-me a cacofonia). Caso contrário o caractere é discartado por meio das linhas:

evento.preventDefault();

// ou

event.returnValue = false;

No Mozilla as teclas backspace e delete geram o evento onkeypress, o que faz com que o handler do evento seja chamado passando um caractere não aceito, proibindo assim a deleção de um caractere. Então é necessário ainda verificar se o código do caractere digitado é diferente de 8 (código do backspace) e 0 (código do delete).

if(key != 8 && key != 0)
{
      evento.preventDefault();
}

Links sobre o assunto:

Olá galera, depois de alguns dias off, estou de volta!! Hoje vou mostrar como extrair algumas informações de arquivos word (docx)…Estou utilizando o Office 2010. Não testei os códigos deste post em outras versões do Office. Então vamos lá.

Inicialmente precisamos entender a estrutura oculta de um arquivo docx. Para tanto, precisamos apenas abrir o arquivo do word com algum software descompactador de arquivos como Winrar ou Winzip. Após extrair o conteúdo ficamos com a seguinte estrutura de arquivos:

Dentro da pasta word está o arquivo que nos interessa em especial:

Ao abrirmos esse arquivo vemos muitos elementos que inicialmente parecem não fazer sentido:

Pois bem, vamos às explicações:
O arquivo que realmente contém dados como texto e imagens de um arquivo docx é o arquivo document.xml… Como vimos na imagem, esse arquivo contém muitos elementos. Vamos às explicações dos principais elementos:

  • Body: Este elemento é denotado pela tag <w:body> e é ele que contém o corpo de um documento word.
  • Paragraph: Este elemento é denotado pela tag <w:p > e representa um parágrafo dentro do corpo, podendo conter imagem, texto etc…
  • Run: Este elemento é denotado pela tag <w:r> e representa uma espaço para texto, podendo ou não conter texto.
  • Text: Este elemento é denotado pela tag <w:t> e representa um texto. Sempre está associado a uma Run.

Vamos então interagir com um documento word. Nossa missão será extrair todos os textos do arquivo. Para tanto é necessário que tenhamos instalada a Open Xml Sdk 2.0 (Baixar o arquivo com 3 MB). A partir daí é só importar a dll, que fica dentro da pasta que escolhemos durante a instalação. Para que o código funcione, precisamos importar dois namespaces.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

O seguinte código abre um documento word:

var caminhoArquivo = "caminhoParaOArquivo";
using(WordprocessingDocument doc = WordprocessingDocument.Open(caminhoArquivo, false))
{
}

Esse método aceita dois parâmetros: o primeiro é o path para o arquivo a ser aberto e o segundo é booleano indicando se o arquivo será editável. Para termos acesso à parte principal de um arquivo word, acessamos a propriedade MainDocumentPart.Document.Body da classe WordprocessingDocument (Equivalente ao elemento <w:body>)

var caminhoArquivo = "caminhoParaOArquivo";
using(WordprocessingDocument doc = WordprocessingDocument.Open(caminhoArquivo, false))
{
   var corpo = doc.MainDocumentPart.Document.Body;
}

Agora já temos uma referência ao corpo do documento. Para obter o texto do corpo do documento, podemos buscar diretamente pelos elementos Text ou ir entrando na estrutura do documento por etapas. Vamos optar por buscar diretamente pelos elementos Text. Para termos acesso aos textos, basta buscarmos especificamente por todos os elementos descendentes de body que são da classe Text. Usaremos o método Descendents() para tal.

var caminhoArquivo = "caminhoParaOArquivo";
using (WordprocessingDocument documento = WordprocessingDocument.Open(caminhoArquivo, false))
{
    var corpo = documento.MainDocumentPart.Document.Body;
    foreach (var texto in corpo.Descendants<Text>().ToList())
    {
        Console.WriteLine(string.Format("{0}", texto.Text));
    }
}

Eis o resultado: os textos do arquivo impressos no console.

Se quiserem se aprofundar mais no assunto, eis alguns links interessantes:
Open Xml Sdk 2.0 for Microsoft Office
Office Developer Center
OpenXmlDeveloper
Em um próximo momento mostrarei como recuperar imagens de um arquivo word.
Adiós! Finito!

Olá galera!! Hoje vou falar um pouco sobre o jquery mobile, mas antes precisamos de uma definição:
O que é o jQuery Mobile?

jQuery Mobile é uma biblioteca javascript desenvolvida e suportada pelo team jquery(Site do jQuery) para facilitar e padronizar o desenvolvimento de aplicações para dispositivos móveis.

Então vamos lá…
Para utilizarmos o jquery mobile como um renderizador de páginas amigáveis para dispositivos móveis, precisamos, primeiramente, importá-lo. Existem duas maneiras de se importar o conjunto de arquivos necessários para utilizar a biblioteca:

  • Importar o script a partir de uma cópia local.
  • Importar o script a partir de algum CDN (Content Delivery Network) disponível.

Vamos optar por importar os scripts a partir do CDN do próprio jQuery Mobile, uma vez que a importação a partir de um CDN diminui o tempo de carregamento dos scripts, consequentemente aumentando o desempenho da aplicação.

<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.js"></script>

O elemento configura o viewport para pegar a largura do dispositivo e uma escala inicial de 1 (Não se preocupe com isso, apenas copie e cole). Agora podemos seguir em frente e definir a estrutura da página. Segue o código fonte:

<!DOCTYPE html>
<html>
<head>
<title>Aprendendo a usar jQuery Mobile</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h2>Cabeçalho</h2>
</div>
<div data-role="content">
<h2>Conteúdo</h2>
</div>
<div data-role="footer">
<h2>Rodapé</h2>
</div>
</div>
</body>
</html>


Construir páginas que utilizem o jQuery Mobile é apenas um trabalho decorativo…Precisamos apenas colocar atributos específicos em alguns elementos e pronto!! O Framework se encarrega do resto… Vamos entender o código…
Toda página que queremos renderizar deve ter, no mínimo, uma

<div data-role="page">
</div> 

Dentro de uma página, geralmente podemos ter seções de informações divididas em cabeçalho (header), conteúdo (content) e rodapé (footer)…

<div data-role="header"></div>
<div data-role="content"></div>
<div data-role="footer"></div>

Esta é a estrutura mínima de uma página…Podemos inserir quaisquer elementos html e qualquer seção da página normalmente. Podemos, também, customizar a aparência da página apenas decorando os elementos que queremos alterar com atributos específicos:

<div data-role="header" data-theme="b"></div>
<div data-role="content"></div>
<div data-role="footer"></div>


Notem o atributo data-theme=”b”. Este atributo indica ao framework para carregar um css na cor azul para o elemento.
Bom, agora temos uma estrutura básica de uma página mobile…Sinta-se à vontade para brincar com o framework…Na próxima parte desse tema mostrarei como utilizar outros elementos do framework.
Até a próxima!!

Olá galera!! Até que enfim parei para fazer um post no blog….Então vamos lá.

Em um projeto que estou desenvolvendo precisei criar grupos de usuários no sharepoint 2010 via programação, um grupo de Alunos e outro de professores. Eis o resultado:

public class MeuEventReceiver : SPFeatureReceiver
{
// Uncomment the method below to handle the event raised after a feature has been activated.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb site = properties.Feature.Parent as SPWeb)
{
AlterarGrupoAlunos(Status.Adicionar, site);
AlterarGrupoProfessores(Status.Adicionar, site);
}
}
// Uncomment the method below to handle the event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
using (SPWeb site = properties.Feature.Parent as SPWeb)
{
AlterarGrupoAlunos(Status.Remover, site);
AlterarGrupoProfessores(Status.Remover, site);
}
}
private void AlterarGrupoProfessores(Status tipoAlteracao, SPWeb web)
{
if (tipoAlteracao == Status.Adicionar)
{
bool grupoExistente = false;
try
{
SPGroupCollection groups = web.SiteGroups;
SPUser owner = web.SiteAdministrators[0];
// Percorrendo a lista de grupos do site
foreach (SPGroup grupo in groups)
{
if (grupo.Name == "Professores")
{
grupoExistente = true;
break;
}
}
// Verificando se o grupo já existe
if (!grupoExistente)
{
// Criando os grupos
groups.Add("Professores", owner, owner, "Grupo de professores do sistema.");
// Associando os grupos ao site
web.AssociatedGroups.Add(groups["Professores"]);
// Persistindo as alterações feitas no site
web.Update();
}
}
catch (Exception)
{
}
}
else if (tipoAlteracao == Status.Remover)
{
try
{
SPGroupCollection groups = web.SiteGroups;
// Percorrendo a lista de grupos do site
foreach (SPGroup grupo in groups)
{
if (grupo.Name == "Professores")
{
// Removendo o grupo
groups.RemoveByID(grupo.ID);
// Persistindo as alterações feitas no site
web.Update();
break;
}
}
}
catch (Exception)
{
}
}
}
private void AlterarGrupoAlunos(Status tipoAlteracao, SPWeb web)
{
if (tipoAlteracao == Status.Adicionar)
{
bool grupoExistente = false;
try
{
SPGroupCollection groups = web.SiteGroups;
SPUser owner = web.SiteAdministrators[0];
// Percorrendo a lista de grupos do site
foreach (SPGroup grupo in groups)
{
if (grupo.Name == "Alunos")
{
grupoExistente = true;
break;
}
}
// Verificando se o grupo já existe
if (!grupoExistente)
{
// Criando os grupos
groups.Add("Alunos", owner, owner, "Grupo de alunos do sistema.");
// Associando os grupos ao site
web.AssociatedGroups.Add(groups["Alunos"]);
// Persistindo as alterações feitas no site
web.Update();
}
}
catch (Exception)
{
}
}
else if (tipoAlteracao == Status.Remover)
{
try
{
SPGroupCollection groups = web.SiteGroups;
// Percorrendo a lista de grupos do site
foreach (SPGroup grupo in groups)
{
if (grupo.Name == "Alunos")
{
// Removendo o grupo
groups.RemoveByID(grupo.ID);
// Persistindo as alterações feitas no site
web.Update();
break;
}
}
}
catch (Exception)
{
}
}
}
private enum Status
{
Adicionar,
Remover
}
}

Agora vamos dar olhada no código. Para que a criação dos grupos seja automática é necessário que usemos o conceito de Event Receivers do SP2010(Sharepoint 2010)…Mas o que são Event Receivers? Event Receivers são classes que possuem eventos associados ao ciclo de vida de uma Feature os quais podemos assinar e gerenciar. No nosso caso precisamos gerenciar os eventos FeatureActivated(Evento disparado após a feature ser ativada) e FeatureDeactivating(Evento disparado quando a feature está sendo desativada). Ambos eventos recebem um parâmetro do tipo SPFeatureReceiverProperties. Dentro do evento FeatureActivated precisamos criar os grupos, para tanto obtemos uma referência para o site (SPWeb) ao qual a feature está sendo associada com o seguinte código:

using (SPWeb site = properties.Feature.Parent as SPWeb)
{
}

Por meio da propriedade Feature do objeto SPFeatureReceiverProperties podemos obter uma referência para o site acessando a propriedade Parent. Uma vez obtido o contexto, devemos verificar se os grupos a serem criados já existem para que não ocorram conflitos em um segundo deploy do pacote que contém a feature. Essa lógica está encapsulada nos métodos AlterarGrupoProfessores e AlterarGrupoAlunos percorrendo a coleção dos grupos associados ao site por meio da propriedade SiteGroups que retorna um objeto do tipo SPGroupCollection.

SPGroupCollection groups = web.SiteGroups;

Logo em seguida precisamos criar os grupos caso não existam. Para criar os grupos precisamos especificar um administrador para o grupo, mas antes precisamos obter uma referência para um administrador para o grupo que pode ser feito por meio da propriedade SiteAdministrators do objeto SPWeb, que retorna um array com os administradores associados ao site:

SPUser owner = web.SiteAdministrators[0];

Por fim, para criar o grupo usamos o método Add do objeto SPGroupCollection:

groups.Add("Alunos", owner, owner, "Grupo de alunos do sistema.");

O primeiro parâmetro é o nome do grupo, o segundo é o proprietário do grupo, o terceiro o usuário padrão e o último uma descrição do grupo. No entato, para que sejam feitas as mudanças precisamos adicionar o grupo criado ao conjunto de grupos associados ao site e depois atualizá-lo, o que é feito por meio do seguinte código:

// Associando os grupos ao site
web.AssociatedGroups.Add(groups["Alunos"]);
// Persistindo as alterações feitas no site
web.Update();

Pronto, adicionamos um grupo no SP2010. Agora precisamos exclui-lo quando a feature for desativada. No evento FeatureDeactivating, precisamos verificar se o grupo que queremos excluir já existe. Caso exista, precisamos excluir. Isso é feito por meio do método RemoveById que recebe como parâmetro o Id do grupo a ser excluído:

// Removendo o grupo
groups.RemoveByID(grupo.ID);

Pronto!!! Isso é tudo!! Finito…ahsuahs…Até a próxima!!

Olá galera, estou abrindo esse blog para compartilhar minhas experiências com o desenvolvimento de software principalmente direcionado à plataforma .Net.

Em breve postarei algo…

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.