28 mars 2011

INFOPATH : Ajout pièce jointe

Récemment, je suis tombé sur la problèmatique de préremplir le champ de pièce jointe d'un formulaire InfoPath. Cette opération s'avère plus compliqué que ce que l'on croit à cause du principe de fonctionnement du champ pièce jointe d'InfoPath (le document est stocké en binary64 dans le xml et le nom du document est encodé dans la chaine).

Le petit bout de code suivant vous permettra d'insérer facilement des données dans un champ pièce jointe:
public String CreateInfoPathAttachment(String fileName, byte[] fileData)
{
   // This memory stream for InfoPath attachment buffer before Base64 encoding.
   using (MemoryStream ms = new MemoryStream())
   {
          uint fileNameLength = (uint)fileName.Length + 1;
          byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);
          using (BinaryWriter bw = new BinaryWriter(ms);
          {
                    // Write the InfoPath attachment signature.
                    bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 });
                    // Write the default header information.
                    bw.Write((uint)0x14); // size
                    bw.Write((uint)0x01); // version
                    bw.Write((uint)0x00); // reserved

                    // Write the file size.
                    bw.Write((uint)fileData.Length);

                    // Write the size of the file name.
                    bw.Write((uint)fileNameLength);

                    // Write the file name (Unicode encoded).
                    bw.Write(fileNameBytes);

                    // Write the file name terminator. This is two nulls in Unicode.
                    bw.Write(new byte[] { 0, 0 });
                    bw.Write(fileData);
          }
          return Convert.ToBase64String(ms.ToArray());
   }
}
Ensuite il suffit d'appeler cette fonction de la manière suivante:


XPathNavigator PJ = this.MainDataSource.CreateNavigator().SelectSingleNod("//my:PJ", NamespaceManager);
if (PJ.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))
          PJ.DeleteSelf();
string s = CreateInfoPathAttachment("toto.gif",fileBuffer);
PJ.SetValue(s);

24 mars 2011

INFOPATH : Desactiver fermeture formulaire

Aujourd'hui un petit post afin de parler d'une fonctionnalité souvent souhaitée dans les formulaires InfoPath : a savoir, le masquage de la croix de fermeture du formulaire (cela permet de maitriser l'utilisation du formulaire par l'utilisateur puisqu'il sera obligé de fermer par un bouton dans le formulaire).
Pour cela, il faut utiliser du code managé dans le formulaire InfoPath (à insérer dans la classe 'FormCode'):
private const int SC_CLOSE = 61536;
private const int MF_BYCOMMAND = 0;
private const int MF_GRAYED = 1;
private const int MF_ENABLED = 0;

// Récupère le handle d'une fenêtre à partir de son titre
[DllImport("user32.dll", EntryPoint = "FindWindowA")]
private static extern int FindWindow(string lpClassName, string lpWindowName);

// Fonctions de gestions des menus systèmes windows
[DllImport("user32.dll")]
private static extern int GetSystemMenu(int hwnd, int revert);
[DllImport("user32.dll")]
private static extern int EnableMenuItem(int menu, int ideEnableItem, int enable);

public static void Disable(int handle)
{
// The return value specifies the previous state of the menu item (it is either
// MF_ENABLED or MF_GRAYED). 0xFFFFFFFF indicates that the menu item does not exist.
switch (EnableMenuItem(GetSystemMenu(handle, 0), SC_CLOSE, (MF_BYCOMMAND
MF_GRAYED)))
{
case MF_ENABLED:
break;
case MF_GRAYED:
break;
default:
// throw new Exception("Le handle ne renvoie rien.");
break;
}
}

Ensuite il faut copier ces 3 lignes de code dans la partie "form_loading" de votre formulaire (Pour appeler cet évènement, il faut aller dans le menu "Insertion" d'InfoPath puis cliquer sur "Evènement au chargement"):

int myWindow;
myWindow = FindWindow(null, this.Application.Name);
Disable(myWindow);
Par contre, cette méthode appelant des composants système, il faudra que le formulaire soit en mode "Full Trust" au niveau de la sécurité (Onglet "Outils/Options du formulaire/Sécurité").

Cette méthode a été implémentée sur un projet InfoPath 2007 et fonctionne à merveille.

5 mars 2011

SHAREPOINT 2010 : Personnaliser liste avec InfoPath

Comme nous l'avons vu précédemment, une des nouvelles fonctionnalités de SharePoint 2010 est l'apparition de la possiblilité de modifier des formulaires de liste directement avec InfoPath.
Que ce soit pour la création d'un élément de liste, sa consultation ou sa modification.
Dans la version 2007, il fallait développer un nouveau formulaire ASP.Net héritant de l'original SharePoint afin de réaliser ceci. Autant dire qu'InfoPath simplifie encore une fois grandement le développement et permet un gain de temps énorme.

Les deux tutoriels suivants permettront d'appréhender facilement la méthode à suivre (ce sont de très bons tutos) :
A noter toutefois que la deuxième méthode à l'avantage de pouvoir accueillir du code personnalisé (l'onglet "Développeur" étant disponible dans le formulaire InfoPath)... Ce qui n'est pas la cas lors du clic sur le ruban d'une liste SharePoint.

De plus, un problème connu dans cette version de SharePoint est le fait que le bouton "Personnaliser le formulaire" disponible dans le ruban n'est parfois pas cliquable. Si tel est le cas, il suffit de modifier la zone de votre site SharePoint dans Internet Explorer (en le plaçant dans les sites de confiance par exemple).

Bonne customisation.