I asked ChatGPT to help with this one, and the answer seemed reasonable (though I didn't check the code).
I post my question and the reply below.
Write back if you have any follow-up questions that I can ask the chat bot.
----------
Q: I am developing an Office add-in in C#, with a Ribbon extension that has a toggleButton (not using VSTO). How should the toggleButton markup and handlers look, if I want the toggle state to be persistent between Excel sessions?
A: To create a persistent toggleButton in a C# Office add-in with a Ribbon extension, you'll need to save the toggle state in a persistent storage, like the Windows Registry or a configuration file. In this example, we'll use the Windows Registry to store the toggle state.
Here's the XML markup for your Ribbon:
<customUI xmlns="
http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="MyTab" label="My Tab">
<group id="MyGroup" label="My Group">
<toggleButton id="myToggleButton" label="Toggle Button" onAction="OnToggleButtonAction" getPressed="GetToggleButtonPressed" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Now, create a C# class that implements the IRibbonExtensibility interface and the required callback methods:
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Office.Core;
using Microsoft.Win32;
namespace MyOfficeAddin
{
[ComVisible(true)]
public class Ribbon : IRibbonExtensibility
{
private IRibbonUI ribbon;
public Ribbon()
{
}
public string GetCustomUI(string ribbonID)
{
return GetResourceText("MyOfficeAddin.Ribbon.xml");
}
public void OnToggleButtonAction(IRibbonControl control, bool isPressed)
{
SaveToggleButtonState(isPressed);
}
public bool GetToggleButtonPressed(IRibbonControl control)
{
return GetToggleButtonState();
}
private static string GetResourceText(string resourceName)
{
Assembly asm = Assembly.GetExecutingAssembly();
string[] resourceNames = asm.GetManifestResourceNames();
for (int i = 0; i < resourceNames.Length; ++i)
{
if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
{
using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
{
if (resourceReader != null)
{
return resourceReader.ReadToEnd();
}
}
}
}
return null;
}
private void SaveToggleButtonState(bool isPressed)
{
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\MyCompany\MyOfficeAddin");
key.SetValue("ToggleState", isPressed, RegistryValueKind.DWord);
key.Close();
}
private bool GetToggleButtonState()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\MyCompany\MyOfficeAddin");
if (key == null)
{
return false; // Default state
}
object stateValue = key.GetValue("ToggleState");
key.Close();
if (stateValue == null)
{
return false; // Default state
}
return ((int)stateValue) == 1;
}
}
}
In this example, the SaveToggleButtonState method saves the toggle state to the Windows Registry, and the GetToggleButtonState method reads the state from the Registry. The GetToggleButtonPressed callback initializes the toggleButton state when the Ribbon is loaded, and the OnToggleButtonAction callback saves the new state when the button is toggled. This will ensure the state is persistent between Excel sessions.