VSTO - idQ not firing callbacks
L’autre jour, petit problème chez un client concernant un add-in VSTO pour Outlook. Celui-ci est composé de différent rubans personnalisés via des fichiers XML (donc sans designer) et étend les fonctionnalités de gestion de mail notamment en permettant un enregistrement en base de données.
La demande du jour était alors de rendre cet add-in plus facilement modifiable, et surtout localizable (gestion du multilangue).
Ma solution fut alors d’utiliser des fichiers de ressources et surtout au niveau de chaque contrôle du ruban, d’utiliser une méthodologie la plus générique possible pour pouvoir un code facilement maintenable : l’utilisation de callbacks communs.
Ainsi, nous obtenions un code xml simple :
<button id="AddMinute"
onAction="btnNewMinute_Click"
imageMso="QueryShowTable"
getLabel="GetLabel"
getDescription="GetDescription"
getScreentip="GetScreenTip"
getSupertip="GetSuperTip"
size="large"
/>
Et un code-behind relativement simple
/// <summary>
/// Callback method to return the label of the control
/// </summary>
/// <param name="control">The control which launchs the callback</param>
/// <returns>The label of the control</returns>
public string GetLabel(IRibbonControl control)
{
return Ressources.UILabels.ResourceManager.GetString(control.Id);
}
/// <summary>
/// Callback method to return the ScreenTip of the control
/// </summary>
/// <param name="control">The control which launchs the callback</param>
/// <returns>The ScreenTip of the control</returns>
public string GetScreenTip(IRibbonControl control)
{
return Ressources.UILabels.ResourceManager.GetString(control.Id + "ScreenTip");
}
/// <summary>
/// Callback method to return the SuperTip of the control
/// </summary>
/// <param name="control">The control which launchs the callback</param>
/// <returns>The SuperTip of the control</returns>
public string GetSuperTip(IRibbonControl control)
{
return Ressources.UILabels.ResourceManager.GetString(control.Id + "SuperTip");
}
/// <summary>
/// Callback method to return the description of the control
/// </summary>
/// <param name="control">The control which launchs the callback</param>
/// <returns>The description of the control</returns>
public string GetDescription(IRibbonControl control)
{
return Ressources.UILabels.ResourceManager.GetString(control.Id + "Description");
}
Ce qui permet d’ajouter autant de contrôles que nécessaire et gérer leur affichage via des fichiers de ressources.
Seul problème, à partir du moment où l’on indique des qualified id (idQ), les callbacks sont désactivés et ne s’exécutent plus. Ainsi, le fait de passer de <button id="AddMinute" à <button idQ="lgm:AddMinute" empêche la solution de fonctionner et si l’addin semble marcher parfaitement, les labels, ne sont eux, pas chargés.
Le problème vient en réalité du namespace déclaré dans le XML
<customUI onLoad="Ribbon_Load" xmlns="https://schemas.microsoft.com/office/2006/01/customui"
xmlns:lgm="RibbonAddin">
Celui-ci doit être déclaré mais surtout, correspondre au namespace de votre code-behind (normalement le namespace de votre projet d’addin). Ainsi le namespace suivant rend les callbacks inopérants
xmlns:lgm="any-other-namespace-is-a-bad-idea">
C’est un détail mais l’oublier peut simplement vous rendre fou et vous faire perdre plein de temps!