Add sample for Settings API (#412)
* Add sample for Settings API --------- Co-authored-by: Charles Willis <chawill@microsoft.com>
This commit is contained in:
Родитель
23317634f0
Коммит
8b4ca15be7
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"SettingsSample.MyToolWindowCommand.DisplayName": "Sample Text Tool Window",
|
||||
"SettingsSample.Settings.Category.DisplayName": "Settings Sample",
|
||||
"SettingsSample.Settings.Category.Description": "Settings for the LoremIpsum sample generator.",
|
||||
"SettingsSample.Settings.AutoUpdate.DisplayName": "Auto Update",
|
||||
"SettingsSample.Settings.AutoUpdate.Description": "Whether to update the sample text when a setting changes.",
|
||||
"SettingsSample.Settings.TextLength.DisplayName": "Text Length",
|
||||
"SettingsSample.Settings.TextLength.Description": "Number of characters to include in the generated text.",
|
||||
"SettingsSample.Settings.QuoteStyle.DisplayName": "Quote Style",
|
||||
"SettingsSample.Settings.QuoteStyle.Description": "Style of quotes to enclose the generated text.",
|
||||
"SettingsSample.Settings.QuoteStyle.None": "None",
|
||||
"SettingsSample.Settings.QuoteStyle.Single": "Single",
|
||||
"SettingsSample.Settings.QuoteStyle.Double": "Double"
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Extensibility;
|
||||
using Microsoft.VisualStudio.Extensibility.ToolWindows;
|
||||
using Microsoft.VisualStudio.RpcContracts.RemoteUI;
|
||||
|
||||
/// <summary>
|
||||
/// A sample tool window.
|
||||
/// </summary>
|
||||
[VisualStudioContribution]
|
||||
public class MyToolWindow : ToolWindow
|
||||
{
|
||||
private MyToolWindowData? dataContext;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MyToolWindow" /> class.
|
||||
/// </summary>
|
||||
public MyToolWindow()
|
||||
{
|
||||
this.Title = "Settings Sample Tool Window";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ToolWindowConfiguration ToolWindowConfiguration => new()
|
||||
{
|
||||
Placement = ToolWindowPlacement.DocumentWell,
|
||||
AllowAutoCreation = false,
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task InitializeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
this.dataContext = new MyToolWindowData(this.Extensibility);
|
||||
return this.dataContext.InitializeAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IRemoteUserControl> GetContentAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult<IRemoteUserControl>(new MyToolWindowControl(this.dataContext));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.Extensibility;
|
||||
using Microsoft.VisualStudio.Extensibility.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// A sample command for showing a tool window.
|
||||
/// </summary>
|
||||
[VisualStudioContribution]
|
||||
public class MyToolWindowCommand : Command
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override CommandConfiguration CommandConfiguration => new("%SettingsSample.MyToolWindowCommand.DisplayName%")
|
||||
{
|
||||
Placements = [CommandPlacement.KnownPlacements.ToolsMenu],
|
||||
Icon = new(ImageMoniker.KnownValues.ToolWindow, IconSettings.IconAndText),
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.Extensibility.Shell().ShowToolWindowAsync<MyToolWindow>(activate: true, cancellationToken);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.Extensibility.UI;
|
||||
|
||||
/// <summary>
|
||||
/// A sample remote user control to use as tool window UI content.
|
||||
/// </summary>
|
||||
internal class MyToolWindowControl : RemoteUserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MyToolWindowControl" /> class.
|
||||
/// </summary>
|
||||
/// <param name="dataContext">
|
||||
/// Data context of the remote control which can be referenced from xaml through data binding.
|
||||
/// </param>
|
||||
public MyToolWindowControl(object? dataContext)
|
||||
: base(dataContext)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vs="http://schemas.microsoft.com/visualstudio/extensibility/2022/xaml"
|
||||
xmlns:styles="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"
|
||||
xmlns:colors="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0">
|
||||
<Border Background="{DynamicResource {x:Static colors:EnvironmentColors.ToolWindowBackgroundBrushKey}}"
|
||||
TextElement.Foreground="{DynamicResource {x:Static colors:EnvironmentColors.ToolWindowTextBrushKey}}"
|
||||
Padding="5">
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Margin="0,0,5,0"
|
||||
Text="Sample Text:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="SampleTextBlock"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding SampleText, Mode=OneWay}"
|
||||
Style="{StaticResource {x:Static styles:VsResourceKeys.TextBlockEnvironment155PercentFontSizeStyleKey}}">
|
||||
</TextBlock>
|
||||
<Button x:Name="UpdateButton"
|
||||
Content="Update Sample Text From Settings"
|
||||
IsEnabled="{Binding ManualUpdate}"
|
||||
Margin="0,10,0,0"
|
||||
MinHeight="25"
|
||||
MinWidth="60"
|
||||
Style="{StaticResource {x:Static styles:VsResourceKeys.ButtonStyleKey}}"
|
||||
Command="{Binding UpdateCommand}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft;
|
||||
using Microsoft.VisualStudio.Extensibility;
|
||||
using Microsoft.VisualStudio.Extensibility.Settings;
|
||||
using Microsoft.VisualStudio.Extensibility.UI;
|
||||
|
||||
/// <summary>
|
||||
/// A sample data context object to use with tool window UI content.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
internal class MyToolWindowData : NotifyPropertyChangedObject
|
||||
{
|
||||
internal static readonly string LoremIpsumText = """
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing elit dignissim lacinia donec,
|
||||
praesent diam ac mattis morbi nisi dictum dapibus. Convallis natoque interdum
|
||||
curabitur malesuada tellus aliquam dignissim hendrerit tempor, primis sem nulla
|
||||
neque cubilia rutrum mollis nisl, eleifend imperdiet lacinia fames gravida sed mus
|
||||
magnis. Pretium aliquet consequat curabitur eros eleifend praesent, nostra malesuada
|
||||
hendrerit ornare volutpat, cubilia aptent at mollis convallis.
|
||||
""";
|
||||
|
||||
private readonly VisualStudioExtensibility extensibility;
|
||||
private string sampleText = LoremIpsumText;
|
||||
private bool manualUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MyToolWindowData" /> class.
|
||||
/// </summary>
|
||||
/// <param name="extensibility">
|
||||
/// Extensibility object instance.
|
||||
/// </param>
|
||||
public MyToolWindowData(VisualStudioExtensibility extensibility)
|
||||
{
|
||||
this.extensibility = Requires.NotNull(extensibility, nameof(extensibility));
|
||||
|
||||
this.UpdateCommand = new AsyncCommand(this.UpdateAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the async command used to show a message prompt.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public IAsyncCommand UpdateCommand
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the user must
|
||||
/// click the "Update" button to refresh the sample text.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public bool ManualUpdate
|
||||
{
|
||||
get => this.manualUpdate;
|
||||
set => this.SetProperty(ref this.manualUpdate, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to display in the message prompt.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string SampleText
|
||||
{
|
||||
get => this.sampleText;
|
||||
set => this.SetProperty(ref this.sampleText, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the current instance of <see cref="MyToolWindowData"/>.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">Cancellation token to monitor.</param>
|
||||
/// <returns>Task indicating completion of initialization.</returns>
|
||||
public Task InitializeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return this.InitializeSettingsAsync(cancellationToken);
|
||||
}
|
||||
|
||||
#pragma warning disable VSEXTPREVIEW_SETTINGS // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
private async Task InitializeSettingsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await this.extensibility.Settings().SubscribeAsync(
|
||||
[SettingDefinitions.SettingsSampleCategory],
|
||||
cancellationToken,
|
||||
values =>
|
||||
{
|
||||
if (values.TryGetValue(SettingDefinitions.AutoUpdateSetting.FullId, out ISettingValue? autoUpdateValue))
|
||||
{
|
||||
this.ManualUpdate = !autoUpdateValue.Value<bool>();
|
||||
}
|
||||
|
||||
if (!this.ManualUpdate)
|
||||
{
|
||||
this.UpdateSampleTextFromSettings(values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UpdateAsync(object? commandParameter, CancellationToken cancellationToken)
|
||||
{
|
||||
SettingValues values = await this.extensibility.Settings().ReadEffectiveValuesAsync(
|
||||
[SettingDefinitions.SettingsSampleCategory],
|
||||
cancellationToken);
|
||||
|
||||
this.UpdateSampleTextFromSettings(values);
|
||||
}
|
||||
|
||||
private void UpdateSampleTextFromSettings(SettingValues values)
|
||||
{
|
||||
string text = LoremIpsumText;
|
||||
|
||||
if (values.TryGetValue(SettingDefinitions.TextLengthSetting.FullId, out ISettingValue? textLengthValue))
|
||||
{
|
||||
int length = textLengthValue.Value<int>();
|
||||
text = LoremIpsumText[..Math.Min(length, LoremIpsumText.Length)];
|
||||
}
|
||||
|
||||
if (values.TryGetValue(SettingDefinitions.QuoteStyleSetting.FullId, out ISettingValue? quoteStyleValue))
|
||||
{
|
||||
this.SampleText = quoteStyleValue.Value<string>() switch
|
||||
{
|
||||
"single" => $"'{text}'",
|
||||
"double" => $"\"{text}\"",
|
||||
_ => text,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore VSEXTPREVIEW_SETTINGS // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
title: Extension Settings Sample reference
|
||||
description: A reference sample for extensions settings
|
||||
date: 2024-08-20
|
||||
---
|
||||
|
||||
# Walkthrough: Extension Settings Sample
|
||||
|
||||
This is a simple extension that shows how settings can be added to Visual Studio and read to configure the behavior of a tool window.
|
||||
|
||||
## Tool window definition
|
||||
|
||||
See the [ToolWindowSample](../ToolWindowSample/README.md) for more information on defining the tool window.
|
||||
|
||||
## Setting definitions
|
||||
|
||||
The extension contains a [code file](./SettingDefinitions.cs) that defines three settings and a parent category to contain them. Each setting and the category starts with the `VisualStudioContribution` class attribute which makes it available to Visual Studio:
|
||||
|
||||
```csharp
|
||||
[VisualStudioContribution]
|
||||
internal static SettingCategory SettingsSampleCategory { get; } = new("settingsSample", "%SettingsSample.Settings.Category.DisplayName%")
|
||||
{
|
||||
Description = "%SettingsSample.Settings.Category.Description%",
|
||||
};
|
||||
```
|
||||
|
||||
```csharp
|
||||
[VisualStudioContribution]
|
||||
internal static Setting.Boolean AutoUpdateSetting { get; } = new("autoUpdate", "%SettingsSample.Settings.AutoUpdate.DisplayName%", SettingsSampleCategory, defaultValue: true)
|
||||
{
|
||||
Description = "%SettingsSample.Settings.AutoUpdate.Description%",
|
||||
};
|
||||
|
||||
The `SettingCategory` and `Setting.Boolean` properties define information about the settings that is available to Visual Studio even before the extension is loaded.
|
||||
|
||||
In `MyToolWindowData`, a subscription is created to read and monitor value changes for all the settings in the `SettingSampleCategory`:
|
||||
|
||||
```csharp
|
||||
public MyToolWindowData(VisualStudioExtensibility extensibility)
|
||||
{
|
||||
...
|
||||
this.InitializeSettingsAsync(extensibility).Forget();
|
||||
}
|
||||
private async Task InitializeSettingsAsync(VisualStudioExtensibility extensibility)
|
||||
{
|
||||
await extensibility.Settings().SubscribeAsync(
|
||||
[SettingDefinitions.SettingsSampleCategory],
|
||||
CancellationToken.None,
|
||||
values => {...});
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Once deployed, the "Sample Text Tool Window" command can be used to show the "Settings Sample Tool Window" in the document well.
|
||||
|
||||
### Changing the TextLengthSetting
|
||||
|
||||
Setting values are stored in json files in well-known locations. After deploying the extension:
|
||||
|
||||
* Open the "Sample Text Tool Window": Tools -> Sample Text Tool Window
|
||||
* Open the extension settings json file: Extensions -> Extension Settings (experimental) -> User Scope (current install)
|
||||
|
||||
The `extensibility.settings.json` file will open in an editor. To change the textLength setting, add a value to the file to override
|
||||
the default:
|
||||
|
||||
```json
|
||||
/* Visual Studio Settings File */
|
||||
{
|
||||
"settingsSample.textLength": 150
|
||||
}
|
||||
```
|
||||
|
||||
The string key is the `FullId` property of the `TextLengthSetting` property defined in [SettingDefinitions](./SettingDefinitions.cs). It is formed by the id of the category and the id of the setting.
|
||||
|
||||
Each time you change the value and save the file, the sample text in the tool window will update.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
The settings API is currently experimental, and has several limitations:
|
||||
|
||||
* An extension can only read or write settings from itself or other extensions. Core Visual Studio settings are not available.
|
||||
* There is no UI for extension settings. They can only be changed by using the json files available in the Extensions -> Extension Settings (experimental) menu.
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using Microsoft.VisualStudio.Extensibility;
|
||||
using Microsoft.VisualStudio.Extensibility.Settings;
|
||||
|
||||
#pragma warning disable VSEXTPREVIEW_SETTINGS // The settings API is currently in preview and marked as experimental
|
||||
|
||||
internal static class SettingDefinitions
|
||||
{
|
||||
[VisualStudioContribution]
|
||||
internal static SettingCategory SettingsSampleCategory { get; } = new("settingsSample", "%SettingsSample.Settings.Category.DisplayName%")
|
||||
{
|
||||
Description = "%SettingsSample.Settings.Category.Description%",
|
||||
};
|
||||
|
||||
[VisualStudioContribution]
|
||||
internal static Setting.Boolean AutoUpdateSetting { get; } = new("autoUpdate", "%SettingsSample.Settings.AutoUpdate.DisplayName%", SettingsSampleCategory, defaultValue: true)
|
||||
{
|
||||
Description = "%SettingsSample.Settings.AutoUpdate.Description%",
|
||||
};
|
||||
|
||||
[VisualStudioContribution]
|
||||
internal static Setting.Integer TextLengthSetting { get; } = new("textLength", "%SettingsSample.Settings.TextLength.DisplayName%", SettingsSampleCategory, defaultValue: 10)
|
||||
{
|
||||
Description = "%SettingsSample.Settings.TextLength.Description%",
|
||||
Minimum = 1,
|
||||
Maximum = MyToolWindowData.LoremIpsumText.Length,
|
||||
};
|
||||
|
||||
[VisualStudioContribution]
|
||||
internal static Setting.Enum QuoteStyleSetting { get; } = new(
|
||||
"quoteStyle",
|
||||
"%SettingsSample.Settings.QuoteStyle.DisplayName%",
|
||||
SettingsSampleCategory,
|
||||
[new EnumSettingEntry("none", "%SettingsSample.Settings.QuoteStyle.None%"), new EnumSettingEntry("single", "%SettingsSample.Settings.QuoteStyle.Single%"), new EnumSettingEntry("double", "%SettingsSample.Settings.QuoteStyle.Double%")],
|
||||
defaultValue: "double")
|
||||
{
|
||||
Description = "%SettingsSample.Settings.QuoteStyle.Description%",
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>12</LangVersion>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.11.40261" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.11.40261" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="MyToolWindowControl.xaml" />
|
||||
<Page Remove="MyToolWindowControl.xaml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace SettingsSample;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.VisualStudio.Extensibility;
|
||||
|
||||
/// <summary>
|
||||
/// Extension entry point for the SettingsSample.
|
||||
/// </summary>
|
||||
[VisualStudioContribution]
|
||||
public class SettingsSampleExtension : Extension
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override ExtensionConfiguration ExtensionConfiguration => new()
|
||||
{
|
||||
Metadata = new(
|
||||
id: "SettingsSampleExtension.4ca466cb-dc8d-4216-8323-b5c45f8e0da5",
|
||||
version: this.ExtensionAssemblyVersion,
|
||||
publisherName: "Microsoft",
|
||||
displayName: "Settings Sample Extension",
|
||||
description: "Sample extension demonstrating settings"),
|
||||
};
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void InitializeServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
base.InitializeServices(serviceCollection);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче