VSX技术问询:如何持久化选项页数据及从菜单访问数据
解决VS扩展选项页持久化与菜单访问值的问题
针对你提到的两个问题,我分两部分给你具体的解决方案,都是VS扩展开发里的标准做法:
一、让选项页数据真正持久化(重启VS后不丢失)
VS扩展里的设置持久化最省心的方式是用DialogPage基类,它会自动帮你处理设置的保存和加载,不需要手动读写文件或注册表。下面分两种场景说明:
1. 基于DialogPage的简单选项页
如果你的选项页是继承自DialogPage,只需要确保:
- 把控件对应的字段封装成公共可读写属性(支持序列化的类型,比如string、int、枚举等)
- 用特性注册选项页
举个例子:
using Microsoft.VisualStudio.Shell; using System.ComponentModel; public class MyOptionsPage : DialogPage { // 对应TextBox的属性 [Category("我的设置")] [DisplayName("输入框内容")] [Description("保存用户输入的文本")] public string TextBoxContent { get; set; } = "默认值"; // 对应ComboBox的属性 [Category("我的设置")] [DisplayName("下拉选项")] [Description("保存选中的下拉项")] public string SelectedComboItem { get; set; } = "选项1"; }
然后在你的Package类里注册这个选项页:
[PackageRegistration(UseManagedResourcesOnly = true)] [ProvideOptionPage(typeof(MyOptionsPage), "我的扩展", "通用设置", 0, 0, true)] [Guid("Your-Package-Guid-Here")] public sealed class MyExtensionPackage : Package { // ... 其他代码 }
这样设置会自动保存到VS的全局设置存储里(路径大概是%AppData%\Microsoft\VisualStudio\<VS版本>\Settings),重启VS后会自动加载,完全不用手动处理保存逻辑。
2. 自定义WPF用户控件作为选项页内容
如果你的选项页是用WPF用户控件做的自定义UI,需要把控件的属性绑定到DialogPage的公共属性上,这样用户输入的值会同步到属性,进而被VS持久化。
比如你的WPF用户控件XAML里:
<UserControl x:Class="MyExtension.MyOptionsControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MyExtension"> <StackPanel> <TextBox Text="{Binding Path=TextBoxContent, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type local:MyOptionsPage}}}" /> <ComboBox SelectedItem="{Binding Path=SelectedComboItem, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type local:MyOptionsPage}}}" ItemsSource="{Binding ComboItems}"/> </StackPanel> </UserControl>
然后在MyOptionsPage里指定用这个控件作为内容:
public class MyOptionsPage : DialogPage { // 绑定的属性(同之前的例子) public string TextBoxContent { get; set; } = "默认值"; public string SelectedComboItem { get; set; } = "选项1"; // 下拉框的选项列表 public List<string> ComboItems { get; } = new List<string> { "选项1", "选项2", "选项3" }; // 指定自定义控件 protected override IWin32Window Window { get { var control = new MyOptionsControl(); control.DataContext = this; return new WindowWrapper(control); } } } // 辅助类:把WPF控件包装成IWin32Window internal class WindowWrapper : IWin32Window { public WindowWrapper(System.Windows.Media.Visual visual) { Handle = new System.Windows.Interop.WindowInteropHelper(System.Windows.Window.GetWindow(visual)).Handle; } public IntPtr Handle { get; } }
这样用户在自定义UI里输入的内容会自动同步到MyOptionsPage的属性,VS会帮你持久化这些值。
二、从工具菜单访问选项页的值
不管你用哪种方式实现选项页,都可以通过以下两种方法在菜单命令里获取设置值:
方法1:通过DialogPage实例获取(推荐,自动加载最新设置)
在你的菜单命令回调里,直接获取DialogPage的实例,它会自动从设置存储里加载最新的值:
private void ExecuteMyButtonCommand(object sender, EventArgs e) { // 获取选项页实例 var optionsPage = (MyOptionsPage)GetDialogPage(typeof(MyOptionsPage)); // 读取属性值 string textBoxValue = optionsPage.TextBoxContent; string comboValue = optionsPage.SelectedComboItem; // 执行你的业务逻辑 MessageBox.Show($"当前输入框值:{textBoxValue}\n当前下拉选项:{comboValue}"); }
方法2:直接读取VS的SettingsStore
如果你的设置是手动保存到SettingsStore的(比如没用到DialogPage),可以直接读取:
private void ExecuteMyButtonCommand(object sender, EventArgs e) { // 获取SettingsStore服务 var settingsStore = (SettingsStore)GetService(typeof(SVsSettingsStore)); string textBoxValue = "默认值"; // 检查集合是否存在,避免报错 if (settingsStore.CollectionExists("MyExtensionSettings")) { textBoxValue = settingsStore.GetString("MyExtensionSettings", "TextBoxContent"); } // 执行操作 // ... }
最后,确保你的菜单命令已经正确注册到Package类里,比如:
protected override void Initialize() { base.Initialize(); // 获取菜单命令服务 var menuCommandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; if (menuCommandService != null) { // 命令ID(需要和.vsct文件里的对应) var commandId = new CommandID(new Guid("Your-Command-Set-Guid"), 0x0100); var menuItem = new MenuCommand(ExecuteMyButtonCommand, commandId); menuCommandService.AddCommand(menuItem); } }
内容的提问来源于stack exchange,提问作者Icaroto
相关产品推荐
相关产品推荐

