none
Invalidating Ribbon from Outside Ribbon RRS feed

  • Question

  • Hi,

    I'm having problems in invalidating the IRibbonUI object from the document AddIn.

    Say I want to Invalidate the Ribbon whenever the spreadsheet changes. So I have a function in my AddIn that calls the Ribbon Object, which in turn calls its IRibbonUI object's Invalidate() method.

    However, the IRibbonUI object is null whenever I call it from outside. If I call it from a Button callback it works fine. If I call it from another program or in this case, the AddIn, it fails. 

    In AddIn:

    excelChangeHandler = new Excel.DocEvents_ChangeEventHandler(ChangeAction);

    void ChangeAction()

    {

    myRibbon.InvalidateThisRibbon();

    }

    In myRibbon:

    public void InvalidateThisRibbon()

    {

    ribbon.Invalidate(); //<--ribbon is the IRibbonUI object. Error: null

    }

     

    Is there a rule that the Ribbon can only be invalidated when a button or some ribbon control is clicked?

    Any help is appreciated. Thanks.

    Thursday, April 22, 2010 3:42 PM

Answers

  • Hello Alien,

    For this question, it is because that it does not load the xml file, and the Ribbon_Load is not called when using this line "myRibbon = (Ribbon)CreateRibbonExtensibilityObject(). So ribbon in your code is null. You could set breakpoints to all this code, debug it step to step. When we running this add-in under Visual Studio, first it will call CreateRibbonExtensibilityObject method, load ribbon xml file, and call CreateRibbonExtensibilityObject again. When calling Ribbon_Load, this callback procedure receives an IRibbonUI object as a parameter, and we could cache this reference for later invalidating ribbon. For this, please refer to this MSDN page: http://msdn.microsoft.com/en-us/library/aa338202.aspx#OfficeCustomizingRibbonUIforDevelopers_Dynamically. For this, I define a class-level Office.IRibbonUI in ThisAddIn class, and set the value of this in Ribbon_Load callback.

    I have made a change for code above, and it works fine in my side. Code like this,

    Ribbon.cs

      [ComVisible(true)]
      public class Ribbon2 : Office.IRibbonExtensibility
      {
        public Office.IRibbonUI ribbon;
        public Ribbon2()
        {
         }
        public void Ribbon_Load(Office.IRibbonUI ribbonUI)
        {
          this.ribbon = ribbonUI;
          Globals.ThisAddIn.ribbon = this.ribbon;
        }
    
        public bool GetButtonVisible(Office.IRibbonControl control)
        {
           return Globals.ThisAddIn.bvisible;          
        }
      }

    ThisAddIn.cs    

     public partial class ThisAddIn
      {    
        public Office.IRibbonUI ribbon;
        public bool bvisible;
        Excel.Worksheet sheet; 
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
          bvisible = true;
          sheet =Globals.ThisAddIn.Application.ActiveSheet as Excel.Worksheet;
          sheet.Change +=new Microsoft.Office.Interop.Excel.DocEvents_ChangeEventHandler(sheet_Change); 
        }
        void sheet_Change(Microsoft.Office.Interop.Excel.Range Target)
        {
          bvisible = !bvisible;     
          ribbon.Invalidate();
        }
        protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
        {
          return new Ribbon2();
        }
      }

    If you have any concern for this, please feel free to follow up.

    Best regards,
    Bessie
     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Thursday, April 29, 2010 5:27 AM

All replies

  • It is not clear from above how you are getting reference to myRibbon in the variable. I tried following code and it works like a charm. Copy pasting the code here as for reason the Insert Code function is not working right now.

    Ribbon1.cs

     

    private void Ribbon1_Load(object sender, RibbonUIEventArgs e)

    {

     

    Globals.ThisAddIn.ribbon = this;

    }

     

    internal void invalidateThisRibbon()

    {

     

    this.RibbonUI.Invalidate();

    }

     

    ThisAddIn.cs

     

    public Ribbon1 ribbon;

    Excel.

    Worksheet sheet;

     

    private void ThisAddIn_Startup(object sender, System.EventArgs e)

    {

    sheet =

    Globals.ThisAddIn.Application.ActiveSheet as Excel.Worksheet;

    sheet.Change +=

    new Microsoft.Office.Interop.Excel.DocEvents_ChangeEventHandler(sheet_Change);

    }

     

    void sheet_Change(Microsoft.Office.Interop.Excel.Range Target)

    {

    ribbon.invalidateThisRibbon();

    }

    Friday, April 23, 2010 1:05 AM
    Moderator
  • Hi Navneet,
    Thanks for the reply.

    You're right, the code you posted works. However, I'm using Office.IRibbonExtensibility instead of OfficeRibbon. So I'm not really using the Ribbon Designer tool in VSTO, using the XML instead.

    Here's the code I'm using: Ribbon.cs
    public class Ribbon : Office.IRibbonExtensibility
       {
          private Office.IRibbonUI ribbon;
          bool buttonVisible;
    
          public Ribbon()
          {
             buttonVisible = true;
          }
    
          public string GetCustomUI(string ribbonID)
          {
             return GetResourceText("ExcelAddIn1.Ribbon.xml");
          }
         
          public void Ribbon_Load(Office.IRibbonUI ribbonUI)
          {
             this.ribbon = ribbonUI;
          }
    
          public void InvalidateThisRibbon()
          {
             buttonVisible = !buttonVisible;
             this.ribbon.Invalidate();
          }
    
          public bool GetButtonVisible(Office.IRibbonControl control)
          {
             return buttonVisible;
          }
    
       }


    ThisAddIn.cs

    public partial class ThisAddIn
        {
           Ribbon myRibbon;
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
               myRibbon = (Ribbon)CreateRibbonExtensibilityObject();
               Excel.Worksheet sheet = (Excel.Worksheet)Globals.ThisAddIn.Application.ActiveSheet;
    
               sheet.Change += new Microsoft.Office.Interop.Excel.DocEvents_ChangeEventHandler(sheet_Change);
            }
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
            }
    
            void sheet_Change(Microsoft.Office.Interop.Excel.Range Target)
            {
    
               myRibbon.InvalidateThisRibbon();
    
            }
    
            protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
            {
               return new Ribbon();
            }
    }


    In case you want the Ribbon.xml, here it is:

    <?xml version="1.0" encoding="UTF-8"?>
    <customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
       <ribbon>
          <tabs>
             <tab idMso="TabAddIns">
                <group id="group1" label="group1">
                   <labelControl id="label1" label="RibbonTest" />
                   <checkBox id="checkBox1" label="checkBox1" />
                   <button id="button1" label="button1" showImage="false" getVisible="GetButtonVisible" />
                </group>
             </tab>
          </tabs>
       </ribbon>
    </customUI>


    In this case, the RibbonUI object is null whenever I try to call InvalidateThisRibbon.

    Thanks.
    Wednesday, April 28, 2010 8:29 PM
  • Hi Alien Programmer,

    I think that solution would be to add ComVisible attribute to your Ribbon class. Like this:

     

    [ComVisible(true)]
    public class Ribbon : Office.IRibbonExtensibility
    {
    ...
    }

     

    Hope this helps.

    Regards,
    Dini Selimović

     

    Wednesday, April 28, 2010 9:21 PM
  • Hello Alien,

    For this question, it is because that it does not load the xml file, and the Ribbon_Load is not called when using this line "myRibbon = (Ribbon)CreateRibbonExtensibilityObject(). So ribbon in your code is null. You could set breakpoints to all this code, debug it step to step. When we running this add-in under Visual Studio, first it will call CreateRibbonExtensibilityObject method, load ribbon xml file, and call CreateRibbonExtensibilityObject again. When calling Ribbon_Load, this callback procedure receives an IRibbonUI object as a parameter, and we could cache this reference for later invalidating ribbon. For this, please refer to this MSDN page: http://msdn.microsoft.com/en-us/library/aa338202.aspx#OfficeCustomizingRibbonUIforDevelopers_Dynamically. For this, I define a class-level Office.IRibbonUI in ThisAddIn class, and set the value of this in Ribbon_Load callback.

    I have made a change for code above, and it works fine in my side. Code like this,

    Ribbon.cs

      [ComVisible(true)]
      public class Ribbon2 : Office.IRibbonExtensibility
      {
        public Office.IRibbonUI ribbon;
        public Ribbon2()
        {
         }
        public void Ribbon_Load(Office.IRibbonUI ribbonUI)
        {
          this.ribbon = ribbonUI;
          Globals.ThisAddIn.ribbon = this.ribbon;
        }
    
        public bool GetButtonVisible(Office.IRibbonControl control)
        {
           return Globals.ThisAddIn.bvisible;          
        }
      }

    ThisAddIn.cs    

     public partial class ThisAddIn
      {    
        public Office.IRibbonUI ribbon;
        public bool bvisible;
        Excel.Worksheet sheet; 
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
          bvisible = true;
          sheet =Globals.ThisAddIn.Application.ActiveSheet as Excel.Worksheet;
          sheet.Change +=new Microsoft.Office.Interop.Excel.DocEvents_ChangeEventHandler(sheet_Change); 
        }
        void sheet_Change(Microsoft.Office.Interop.Excel.Range Target)
        {
          bvisible = !bvisible;     
          ribbon.Invalidate();
        }
        protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
        {
          return new Ribbon2();
        }
      }

    If you have any concern for this, please feel free to follow up.

    Best regards,
    Bessie
     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Thursday, April 29, 2010 5:27 AM
  • Thanks a lot Bessie, I simply added an IRibbonUI reference to ThisAddIn, and that worked like a breeze.

     

    Alien

    Thursday, April 29, 2010 1:16 PM
  • Thanks for the illustration
    help me lot.
    Long life  Bessie

     Best Regards.

    Thursday, August 11, 2011 4:44 PM
  •  For WorkBook

            //*********************************************
            Ribbon.xml
            //*********************************************

            <?xml version="1.0" encoding="UTF-8"?>
            <
    customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
                   onLoad="Ribbon_Load">
            <
    ribbon>  
              <
    tabs>
                <
    tab idMso="TabAddIns" >
                  <
    group id="group1" label="group1">
                    <
    labelControl id="label1" label="RibbonTest" />

                    <
    checkBox id="checkBox1" 
                              label="checkBox1" 
                              getEnabled="GetButtonVisible"/>

                    <
    button id="button1"     
                           
    label="button1"
                           
    showImage="false"
                           
    getVisible="GetButtonVisible"
    />
                  </
    group
    >
                </
    tab
    >
                <tab idMso="TabHome" getVisible="GetButtonVisible"/>

              </
    tabs
    >
            </
    ribbon
    >
            </
    customUI>

            //*********************************************
            Ribbon.cs
            //*********************************************
            [ComVisible(true)]
            public class Ribbon : Office.IRibbonExtensibility
            {
              public Office.IRibbonUI ribbon;
              public Ribbon()
              {
              }
     
              public void Ribbon_Load(Office.IRibbonUI ribbonUI)
              {
                this.ribbon = ribbonUI;
                Globals.ThisWorkbook.ribbon = this.ribbon; 
              }
           public bool GetButtonVisible(Office.IRibbonControl control)
              {
                return Globals.ThisWorkbook.bvisible;
              }
            }

    Thursday, August 11, 2011 6:12 PM
  •  

    //*********************************************
    ThisWorkbook.cs
    //*********************************************
     
    public partial class ThisWorkbook
    {
        
    public Office.IRibbonUI ribbon;

            public bool bvisible;

            Excel.Worksheet sheet;

     

          private void ThisWorkbook_Startup(object sender, System.EventArgs e)

          {

               bvisible = true;                      

          }

          protected override Microsoft.Office.Core.IRibbonExtensibility  

          CreateRibbonExtensibilityObject()

          {

                return new Ribbon();

          }

         }

       

            //*********************************************
            sheet2
            //*********************************************
            public partial class Hoja1
            {
              private void Hoja1_ActivateEvent()
              
    {
                  Globals.ThisWorkbook.bvisible = false;           
                  Globals.ThisWorkbook.ribbon.Invalidate();
        
    }
            }

     

            //*********************************************
            sheet1
            //*********************************************
            public partial class Hoja1
            {
              private void Hoja1_ActivateEvent()
              
    {
                  Globals.ThisWorkbook.bvisible = true;           
                  Globals.ThisWorkbook.ribbon.Invalidate();
              }
            }

    

    Thursday, August 11, 2011 6:12 PM