Astuce pour les événements COM en VSTO

Si vous développez sous VSTO, il y a une petite chose à savoir qui peut éviter bien des heures de prise de tête. En effet si on se branche sur un événement provenant d'un objet obtenu par la couche d'Interop Office, il faut systématiquement garder en référence membre l'objet sur lequel vous vous êtes branché.

Imaginons la situation suivante, la création d'un bouton sur une Toolbar, il est tentant comme en Winform de créer une variable locale pour la création du bouton et de lui affecter l'événement dans la foulé, comme le code ci-dessous :

private void CreerToolbarEtBouton()
{
  // Création de la barre
  Office.CommandBar oBar = null;

  oBar  = this.Application.ActiveExplorer().CommandBars.Add(MTSInterface._CustomMenuBarName, Office.MsoBarPosition.msoBarTop, Missing.Value, true);
  oBar .Visible = true;

  // Création bouton
  Office.CommandBarButton oButton = null;

  oButton = (Office.CommandBarButton) oBar .Controls.Add(Office.MsoControlType.msoControlButton, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
  oButton.Style = Office.MsoButtonStyle.msoButtonCaption;
  oButton.Caption = "Mon bouton";
  oButton.Visible = true;
  oButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(this.ButtonOptionsEvent);
}

Jusque là rien de bien méchant, cependant le problème avec l'Interop c'est qu'à la fin de la vie d'un objet .Net et ce même si il existe encore du coté COM, tous les abonnements à des événements fait depuis la partie .Net sont supprimés. Du coup dans le cadre de notre bouton, il ne réagira pas au Click.

Vous l'aurez donc compris, pour pouvoir conserver les abonnements il faut systématiquement conserver une référence à l'objet COM dans la partie .Net, la plupart du temps mettre cette référence dans une variable membre suffit amplement. Il faut donc déplacer la déclaration de notre oBouton au niveau de la classe pour résoudre le problème.

J'attire aussi l'attention sur une subtilité au niveau de l'objet Inspectors qui est déclaré au niveau de l'objet Application qui se trouve dans l'Addin. Prenons cet exemple :

this.Application.Inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(this.Inspectors_NewInspector);

Dans cette exemple on peut penser à juste titre qu'il n'y aura pas de problème, car l'événement est bien rattaché à une variable toujours disponible du coté .Net, mais en réalité il n'en est rien. Le désabonnement se fera comme sur l'exemple de notre bouton déclaré localement. Il faut donc extraire l'Inspectors en variable membre pour contourner le problème. Il faut donc déclarer une variable membre et écrire ceci :

private Outlook.Inspectors m_oInspectors;

// ...
// Plus loin dans le code

this.m_oInspectors = this.Application.Inspectors;
this.m_oInspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(this.Inspectors_NewInspector);

Sachant cela, vous n'aurez plus de surprise avec la gestion des événements qui viennent de l'Interop.


Tags: , ,
Catégories: C# | VSTO

0 Commentaires
Actions: Permalink | Comment RSSRSS comment feed

Billets liés

Ajouter un commentaire


 

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Aperçu immédiat

novembre 21. 2008 04:58