如何在Word VSTO插件中扩展RibbonToggleButton接口?
核心思路:装饰器(包装)模式
因为Microsoft.Office.Tools.Ribbon.RibbonToggleButton是接口,直接实现需要编写大量重复代码,我们可以通过包装原生控件实例的方式,复用微软的实现逻辑,同时添加自定义属性。
实现步骤
- 创建自定义类,实现
IRibbonToggleButton接口,内部封装原生控件实例 - 将所有接口成员委托给内部的原生实例
- 添加自己的自定义属性
代码示例
自定义控件类
using Microsoft.Office.Tools.Ribbon; public class MyRibbonToggleButton : IRibbonToggleButton { // 封装微软原生的ToggleButton实例 private readonly IRibbonToggleButton _innerToggleButton; // 自定义属性:示例为自定义标识符 public string CustomButtonId { get; set; } // 构造函数:传入Factory创建的原生实例 public MyRibbonToggleButton(IRibbonToggleButton innerToggleButton) { _innerToggleButton = innerToggleButton; } // 以下为接口成员的委托实现,全部转发给原生实例 public bool Checked { get => _innerToggleButton.Checked; set => _innerToggleButton.Checked = value; } public event RibbonControlEventHandler Click { add => _innerToggleButton.Click += value; remove => _innerToggleButton.Click -= value; } public RibbonFactory Factory => _innerToggleButton.Factory; public string Id => _innerToggleButton.Id; public string Name => _innerToggleButton.Name; public RibbonControlCollection Parent => _innerToggleButton.Parent; public object Tag => _innerToggleButton.Tag; public string Description => _innerToggleButton.Description; public bool Enabled { get => _innerToggleButton.Enabled; set => _innerToggleButton.Enabled = value; } public string ImageName => _innerToggleButton.ImageName; public bool Label { get => _innerToggleButton.Label; set => _innerToggleButton.Label = value; } public string LabelText { get => _innerToggleButton.LabelText; set => _innerToggleButton.LabelText = value; } public bool OfficeImageId { get => _innerToggleButton.OfficeImageId; set => _innerToggleButton.OfficeImageId = value; } public bool ScreenTip { get => _innerToggleButton.ScreenTip; set => _innerToggleButton.ScreenTip = value; } public string ScreenTipText { get => _innerToggleButton.ScreenTipText; set => _innerToggleButton.ScreenTipText = value; } public bool ShowImage { get => _innerToggleButton.ShowImage; set => _innerToggleButton.ShowImage = value; } public bool ShowLabel { get => _innerToggleButton.ShowLabel; set => _innerToggleButton.ShowLabel = value; } public bool SuperTip { get => _innerToggleButton.SuperTip; set => _innerToggleButton.SuperTip = value; } public string SuperTipText { get => _innerToggleButton.SuperTipText; set => _innerToggleButton.SuperTipText = value; } public bool Visible { get => _innerToggleButton.Visible; set => _innerToggleButton.Visible = value; } public void Invalidate() => _innerToggleButton.Invalidate(); public void InvalidateControl() => _innerToggleButton.InvalidateControl(); public void ResumeLayout() => _innerToggleButton.ResumeLayout(); public void ResumeLayout(bool performLayout) => _innerToggleButton.ResumeLayout(performLayout); public void SuspendLayout() => _innerToggleButton.SuspendLayout(); }
在功能区中使用自定义控件
private void Ribbon1_Load(object sender, RibbonUIEventArgs e) { // 1. 用Ribbon Factory创建原生ToggleButton实例 var nativeToggle = this.Factory.CreateRibbonToggleButton(); // 2. 包装成自定义控件 var customToggle = new MyRibbonToggleButton(nativeToggle); // 3. 设置自定义属性 customToggle.CustomButtonId = "Word_AddIn_Custom_Toggle_001"; // 4. 设置原生控件的属性 customToggle.LabelText = "我的自定义开关"; customToggle.ShowImage = true; customToggle.ImageName = "ToggleIcon"; // 5. 添加到功能区组中 this.Group1.Items.Add(customToggle); }
简化方案:利用Tag属性(适合简单场景)
如果只是需要存储少量自定义数据,不需要创建新类,可以直接使用原生控件的Tag属性存储自定义对象:
private void Ribbon1_Load(object sender, RibbonUIEventArgs e) { var toggle = this.Factory.CreateRibbonToggleButton(); // 存储自定义数据 toggle.Tag = new { CustomId = "MyToggle", Description = "自定义开关按钮" }; // 使用时读取数据 var customData = (dynamic)toggle.Tag; string buttonId = customData.CustomId; }
这种方式无需编写大量接口委托代码,适合轻量场景,但缺乏类型安全性。
内容的提问来源于stack exchange,提问作者VA systems engineer
相关产品推荐
相关产品推荐

