提交 24d3c344 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14543 from CyrusNajmabadi/allowDisablingIndentationOrFormatting

Allow disabling of formatting while typing.

Fixes #8224 
Fixes #5873
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
......@@ -35,21 +36,42 @@ public CSharpEditorFormattingService()
{
}
public bool SupportsFormatDocument { get { return true; } }
public bool SupportsFormatOnPaste { get { return true; } }
public bool SupportsFormatSelection { get { return true; } }
public bool SupportsFormatOnReturn { get { return true; } }
public bool SupportsFormatDocument => true;
public bool SupportsFormatOnPaste => true;
public bool SupportsFormatSelection => true;
public bool SupportsFormatOnReturn => true;
public bool SupportsFormattingOnTypedCharacter(Document document, char ch)
{
var options = document.GetOptionsAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None);
var smartIndentOn = options.GetOption(FormattingOptions.SmartIndent) == FormattingOptions.IndentStyle.Smart;
if ((ch == '}' && !options.GetOption(FeatureOnOffOptions.AutoFormattingOnCloseBrace) && !smartIndentOn) ||
(ch == ';' && !options.GetOption(FeatureOnOffOptions.AutoFormattingOnSemicolon)))
// We consider the proper placement of a close curly when it is typed at the start of the
// line to be a smart-indentation operation. As such, even if "format on typing" is off,
// if "smart indent" is on, we'll still format this. (However, we won't touch anything
// else in teh block this close curly belongs to.).
//
// TODO(cyrusn): Should we expose an option for this? Personally, i don't think so.
// If a user doesn't want this behavior, they can turn off 'smart indent' and control
// everything themselves.
if (ch == '}' && smartIndentOn)
{
return true;
}
// If format-on-typing is not on, then we don't support formatting on any other characters.
var autoFormattingOnTyping = options.GetOption(FeatureOnOffOptions.AutoFormattingOnTyping);
if (!autoFormattingOnTyping)
{
return false;
}
if (ch == '}' && !options.GetOption(FeatureOnOffOptions.AutoFormattingOnCloseBrace))
{
return false;
}
if (ch == ';' && !options.GetOption(FeatureOnOffOptions.AutoFormattingOnSemicolon))
{
return false;
}
......@@ -68,9 +90,11 @@ public async Task<IList<TextChange>> GetFormattingChangesAsync(Document document
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var span = textSpan.HasValue ? textSpan.Value : new TextSpan(0, root.FullSpan.Length);
var span = textSpan ?? new TextSpan(0, root.FullSpan.Length);
var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span);
return Formatter.GetFormattedTextChanges(root, new TextSpan[] { formattingSpan }, document.Project.Solution.Workspace, options, cancellationToken);
return Formatter.GetFormattedTextChanges(root,
SpecializedCollections.SingletonEnumerable(formattingSpan),
document.Project.Solution.Workspace, options, cancellationToken);
}
public async Task<IList<TextChange>> GetFormattingChangesOnPasteAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken)
......@@ -100,6 +124,12 @@ private IEnumerable<IFormattingRule> GetFormattingRules(Document document, int p
public async Task<IList<TextChange>> GetFormattingChangesOnReturnAsync(Document document, int caretPosition, CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
if (!options.GetOption(FeatureOnOffOptions.AutoFormattingOnReturn))
{
return null;
}
var formattingRules = this.GetFormattingRules(document, caretPosition);
// first, find the token user just typed.
......@@ -197,24 +227,32 @@ public async Task<IList<TextChange>> GetFormattingChangesAsync(Document document
return null;
}
// don't attempt to format on close brace if autoformat on close brace feature is off, instead just smart indent
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
// don't attempt to format on close brace if autoformat on close brace feature is off, instead just smart indent
bool smartIndentOnly =
token.IsKind(SyntaxKind.CloseBraceToken) &&
!options.GetOption(FeatureOnOffOptions.AutoFormattingOnCloseBrace);
var autoFormattingCloseBraceOff =
!options.GetOption(FeatureOnOffOptions.AutoFormattingOnCloseBrace) ||
!options.GetOption(FeatureOnOffOptions.AutoFormattingOnTyping);
bool smartIndentOnly = token.IsKind(SyntaxKind.CloseBraceToken) && autoFormattingCloseBraceOff;
if (!smartIndentOnly)
if (smartIndentOnly)
{
// if formatting range fails, do format token one at least
var changes = await FormatRangeAsync(document, token, formattingRules, cancellationToken).ConfigureAwait(false);
if (changes.Count > 0)
{
return changes;
}
// if we're only doing smart indent, then ignore all edits to this token that occur before
// the span of the token. They're irrelevant and may screw up other code the user doesn't
// want touched.
var tokenEdits = await FormatTokenAsync(document, token, formattingRules, cancellationToken).ConfigureAwait(false);
var filteredEdits = tokenEdits.Where(t => t.Span.Start >= token.FullSpan.Start).ToList();
return filteredEdits;
}
// if formatting range fails, do format token one at least
var changes = await FormatRangeAsync(document, token, formattingRules, cancellationToken).ConfigureAwait(false);
if (changes.Count > 0)
{
return changes;
}
// if we can't, do normal smart indentation
return await FormatTokenAsync(document, token, formattingRules, cancellationToken).ConfigureAwait(false);
}
......
......@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Implementation.Formatting.Indentation;
using Microsoft.CodeAnalysis.Editor.Implementation.SmartIndent;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.Host.Mef;
......@@ -59,6 +60,11 @@ protected override IFormattingRule GetSpecializedIndentationFormattingRule()
Contract.ThrowIfNull(formattingRules);
Contract.ThrowIfNull(root);
if (!optionSet.GetOption(FeatureOnOffOptions.AutoFormattingOnReturn, LanguageNames.CSharp))
{
return false;
}
if (optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp) != FormattingOptions.IndentStyle.Smart)
{
return false;
......@@ -87,13 +93,15 @@ protected override IFormattingRule GetSpecializedIndentationFormattingRule()
}
var lineOperation = FormattingOperations.GetAdjustNewLinesOperation(formattingRules, previousToken, token, optionSet);
if (lineOperation != null && lineOperation.Option != AdjustNewLinesOption.ForceLinesIfOnSingleLine)
if (lineOperation == null || lineOperation.Option == AdjustNewLinesOption.ForceLinesIfOnSingleLine)
{
return true;
// no indentation operation, nothing to do for smart token formatter
return false;
}
// no indentation operation, nothing to do for smart token formatter
return false;
// We're pressing enter between two tokens, have the formatter figure out hte appropriate
// indentation.
return true;
}
private class FormattingRule : AbstractFormattingRule
......
......@@ -1166,6 +1166,160 @@ class C
await AssertFormatAfterTypeCharAsync(code, expected, optionSet);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task AutoIndentCloseBraceWhenFormatOnTypingIsOff()
{
var code = @"namespace N
{
class C
{
// improperly indented code
int x = 10;
}$$
}
";
var expected = @"namespace N
{
class C
{
// improperly indented code
int x = 10;
}
}
";
var optionSet = new Dictionary<OptionKey, object>
{
{ new OptionKey(FeatureOnOffOptions.AutoFormattingOnTyping, LanguageNames.CSharp), false }
};
await AssertFormatAfterTypeCharAsync(code, expected, optionSet);
}
[WorkItem(5873, "https://github.com/dotnet/roslyn/issues/5873")]
[WpfFact, Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task KeepTabsInCommentsWhenFormattingIsOff()
{
// There are tabs in this test case. Tools that touch the Roslyn repo should
// not remove these as we are explicitly testing tab behavior.
var code =
@"class Program
{
static void Main()
{
return; /* Comment preceded by tabs */ // This one too
}$$
}";
var expected =
@"class Program
{
static void Main()
{
return; /* Comment preceded by tabs */ // This one too
}
}";
var optionSet = new Dictionary<OptionKey, object>
{
{ new OptionKey(FeatureOnOffOptions.AutoFormattingOnTyping, LanguageNames.CSharp), false }
};
await AssertFormatAfterTypeCharAsync(code, expected, optionSet);
}
[WorkItem(5873, "https://github.com/dotnet/roslyn/issues/5873")]
[WpfFact, Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task DoNotKeepTabsInCommentsWhenFormattingIsOn()
{
// There are tabs in this test case. Tools that touch the Roslyn repo should
// not remove these as we are explicitly testing tab behavior.
var code = @"class Program
{
static void Main()
{
return; /* Comment preceded by tabs */ // This one too
}$$
}";
var expected =
@"class Program
{
static void Main()
{
return; /* Comment preceded by tabs */ // This one too
}
}";
await AssertFormatAfterTypeCharAsync(code, expected);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task DoNotFormatStatementIfSemicolonOptionIsOff()
{
var code =
@"namespace N
{
class C
{
int x = 10 ;$$
}
}
";
var expected =
@"namespace N
{
class C
{
int x = 10 ;
}
}
";
var optionSet = new Dictionary<OptionKey, object>
{
{ new OptionKey(FeatureOnOffOptions.AutoFormattingOnSemicolon, LanguageNames.CSharp), false }
};
await AssertFormatAfterTypeCharAsync(code, expected, optionSet);
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task DoNotFormatStatementIfTypingOptionIsOff()
{
var code =
@"namespace N
{
class C
{
int x = 10 ;$$
}
}
";
var expected =
@"namespace N
{
class C
{
int x = 10 ;
}
}
";
var optionSet = new Dictionary<OptionKey, object>
{
{ new OptionKey(FeatureOnOffOptions.AutoFormattingOnTyping, LanguageNames.CSharp), false }
};
await AssertFormatAfterTypeCharAsync(code, expected, optionSet);
}
[WpfFact, WorkItem(4435, "https://github.com/dotnet/roslyn/issues/4435")]
[Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)]
public async Task OpenCurlyNotFormattedIfNotAtStartOfLine()
......
......@@ -18,4 +18,4 @@ public void ExecuteCommand(ReturnKeyCommandArgs args, Action nextHandler)
ExecuteReturnOrTypeCommand(args, nextHandler, CancellationToken.None);
}
}
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Editor.Commands;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.Internal.Log;
......
......@@ -38,7 +38,14 @@ private IEnumerable<IFormattingRule> GetFormattingRules(Document document, int p
var formattingRules = GetFormattingRules(document, lineToBeIndented.Start);
// enter on a token case.
// There are two important cases for indentation. The first is when we're simply
// trying to figure out the appropriate indentation on a blank line (i.e. after
// hitting enter at the end of a line, or after moving to a blank line). The
// second is when we're trying to figure out indentation for a non-blank line
// (i.e. after hitting enter in the middle of a line, causing tokens to move to
// the next line). If we're in the latter case, we defer to the Formatting engine
// as we need it to use all its rules to determine where the appropriate location is
// for the following tokens to go.
if (ShouldUseSmartTokenFormatterInsteadOfIndenter(formattingRules, root, lineToBeIndented, documentOptions, cancellationToken))
{
return null;
......
......@@ -48,11 +48,23 @@ internal static class FeatureOnOffOptions
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PrettyListing"));
[ExportOption]
public static readonly PerLanguageOption<bool> AutoFormattingOnCloseBrace = new PerLanguageOption<bool>(nameof(FeatureOnOffOptions), nameof(AutoFormattingOnCloseBrace), defaultValue: true,
public static readonly PerLanguageOption<bool> AutoFormattingOnTyping = new PerLanguageOption<bool>(
nameof(FeatureOnOffOptions), nameof(AutoFormattingOnTyping), defaultValue: true,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.Auto Formatting On Typing"));
[ExportOption]
public static readonly PerLanguageOption<bool> AutoFormattingOnReturn = new PerLanguageOption<bool>(
nameof(FeatureOnOffOptions), nameof(AutoFormattingOnReturn), defaultValue: true,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.Auto Formatting On Return"));
[ExportOption]
public static readonly PerLanguageOption<bool> AutoFormattingOnCloseBrace = new PerLanguageOption<bool>(
nameof(FeatureOnOffOptions), nameof(AutoFormattingOnCloseBrace), defaultValue: true,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.Auto Formatting On Close Brace"));
[ExportOption]
public static readonly PerLanguageOption<bool> AutoFormattingOnSemicolon = new PerLanguageOption<bool>(nameof(FeatureOnOffOptions), nameof(AutoFormattingOnSemicolon), defaultValue: true,
public static readonly PerLanguageOption<bool> AutoFormattingOnSemicolon = new PerLanguageOption<bool>(
nameof(FeatureOnOffOptions), nameof(AutoFormattingOnSemicolon), defaultValue: true,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.Auto Formatting On Semicolon"));
[ExportOption]
......
......@@ -81,9 +81,9 @@ internal class CSharpVSResources {
/// <summary>
/// Looks up a localized string similar to Automatically format _block on }.
/// </summary>
internal static string Automatically_format_block_on {
internal static string Automatically_format_block_on_close_brace {
get {
return ResourceManager.GetString("Automatically_format_block_on", resourceCulture);
return ResourceManager.GetString("Automatically_format_block_on_close_brace", resourceCulture);
}
}
......@@ -96,12 +96,30 @@ internal class CSharpVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to Automatically format on return.
/// </summary>
internal static string Automatically_format_on_return {
get {
return ResourceManager.GetString("Automatically_format_on_return", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Automatically format _statement on ;.
/// </summary>
internal static string Automatically_format_statement_on {
internal static string Automatically_format_statement_on_semicolon {
get {
return ResourceManager.GetString("Automatically_format_statement_on_semicolon", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Automatically format when typing.
/// </summary>
internal static string Automatically_format_when_typing {
get {
return ResourceManager.GetString("Automatically_format_statement_on", resourceCulture);
return ResourceManager.GetString("Automatically_format_when_typing", resourceCulture);
}
}
......
......@@ -126,13 +126,13 @@
<data name="Insert_Snippet" xml:space="preserve">
<value>Insert Snippet</value>
</data>
<data name="Automatically_format_block_on" xml:space="preserve">
<data name="Automatically_format_block_on_close_brace" xml:space="preserve">
<value>Automatically format _block on }</value>
</data>
<data name="Automatically_format_on_paste" xml:space="preserve">
<value>Automatically format on _paste</value>
</data>
<data name="Automatically_format_statement_on" xml:space="preserve">
<data name="Automatically_format_statement_on_semicolon" xml:space="preserve">
<value>Automatically format _statement on ;</value>
</data>
<data name="Place_members_in_anonymous_types_on_new_line" xml:space="preserve">
......@@ -498,4 +498,10 @@
<data name="Prefer_expression_body" xml:space="preserve">
<value>Prefer expression body</value>
</data>
<data name="Automatically_format_on_return" xml:space="preserve">
<value>Automatically format on return</value>
</data>
<data name="Automatically_format_when_typing" xml:space="preserve">
<value>Automatically format when typing</value>
</data>
</root>
\ No newline at end of file
......@@ -14,8 +14,14 @@
<StackPanel x:Uid="StackPanel_1">
<GroupBox x:Uid="GroupBox_1" Header="General">
<StackPanel x:Uid="StackPanel_2">
<CheckBox x:Name="FormatOnSemicolonCheckBox" x:Uid="FormatOnSemicolonCheckBox" />
<CheckBox x:Name="FormatOnCloseBraceCheckBox" x:Uid="FormatOnCloseBraceCheckBox" />
<CheckBox x:Name="FormatWhenTypingCheckBox" x:Uid="FormatWhenTypingCheckBox"
Checked="FormatWhenTypingCheckBox_Checked"
Unchecked="FormatWhenTypingCheckBox_Unchecked"/>
<StackPanel Margin="15, 0, 0, 0">
<CheckBox x:Name="FormatOnSemicolonCheckBox" x:Uid="FormatOnSemicolonCheckBox" />
<CheckBox x:Name="FormatOnCloseBraceCheckBox" x:Uid="FormatOnCloseBraceCheckBox" />
</StackPanel>
<CheckBox x:Name="FormatOnReturnCheckBox" x:Uid="FormatOnReturnCheckBox" />
<CheckBox x:Name="FormatOnPasteCheckBox" x:Uid="FormatOnPasteCheckBox" />
</StackPanel>
</GroupBox>
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
......@@ -29,13 +17,40 @@ public FormattingOptionPageControl(IServiceProvider serviceProvider) : base(serv
{
InitializeComponent();
FormatOnSemicolonCheckBox.Content = CSharpVSResources.Automatically_format_statement_on;
FormatOnCloseBraceCheckBox.Content = CSharpVSResources.Automatically_format_block_on;
FormatWhenTypingCheckBox.Content = CSharpVSResources.Automatically_format_when_typing;
FormatOnSemicolonCheckBox.Content = CSharpVSResources.Automatically_format_statement_on_semicolon;
FormatOnCloseBraceCheckBox.Content = CSharpVSResources.Automatically_format_block_on_close_brace;
FormatOnReturnCheckBox.Content = CSharpVSResources.Automatically_format_on_return;
FormatOnPasteCheckBox.Content = CSharpVSResources.Automatically_format_on_paste;
BindToOption(FormatOnPasteCheckBox, FeatureOnOffOptions.FormatOnPaste, LanguageNames.CSharp);
BindToOption(FormatWhenTypingCheckBox, FeatureOnOffOptions.AutoFormattingOnTyping, LanguageNames.CSharp);
BindToOption(FormatOnCloseBraceCheckBox, FeatureOnOffOptions.AutoFormattingOnCloseBrace, LanguageNames.CSharp);
BindToOption(FormatOnSemicolonCheckBox, FeatureOnOffOptions.AutoFormattingOnSemicolon, LanguageNames.CSharp);
BindToOption(FormatOnReturnCheckBox, FeatureOnOffOptions.AutoFormattingOnReturn, LanguageNames.CSharp);
BindToOption(FormatOnPasteCheckBox, FeatureOnOffOptions.FormatOnPaste, LanguageNames.CSharp);
SetNestedCheckboxesEnabled();
}
private void FormatWhenTypingCheckBox_Checked(object sender, RoutedEventArgs e)
{
FormatOnCloseBraceCheckBox.IsChecked = true;
FormatOnSemicolonCheckBox.IsChecked = true;
SetNestedCheckboxesEnabled();
}
private void FormatWhenTypingCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
FormatOnCloseBraceCheckBox.IsChecked = false;
FormatOnSemicolonCheckBox.IsChecked = false;
SetNestedCheckboxesEnabled();
}
private void SetNestedCheckboxesEnabled()
{
FormatOnCloseBraceCheckBox.IsEnabled = FormatWhenTypingCheckBox.IsChecked == true;
FormatOnSemicolonCheckBox.IsEnabled = FormatWhenTypingCheckBox.IsChecked == true;
}
}
}
}
\ No newline at end of file
......@@ -17,7 +17,9 @@
<StackPanel>
<CheckBox x:Uid="Show_completion_list_after_a_character_is_typed"
x:Name="Show_completion_list_after_a_character_is_typed"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_list_after_a_character_is_typed}" />
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_list_after_a_character_is_typed}"
Checked="Show_completion_list_after_a_character_is_typed_Checked"
Unchecked="Show_completion_list_after_a_character_is_typed_Unchecked"/>
<StackPanel Margin="15, 0, 0, 0">
<CheckBox x:Uid="Show_completion_list_after_a_character_is_deleted"
x:Name="Show_completion_list_after_a_character_is_deleted"
......
......@@ -20,6 +20,7 @@ public IntelliSenseOptionPageControl(IServiceProvider serviceProvider) : base(se
BindToOption(Show_completion_list_after_a_character_is_typed, CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp);
Show_completion_list_after_a_character_is_deleted.IsChecked = this.OptionService.GetOption(
CompletionOptions.TriggerOnDeletion, LanguageNames.CSharp) == true;
Show_completion_list_after_a_character_is_deleted.IsEnabled = Show_completion_list_after_a_character_is_typed.IsChecked == true;
BindToOption(Never_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.NeverInclude, LanguageNames.CSharp);
BindToOption(Always_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.AlwaysInclude, LanguageNames.CSharp);
......@@ -30,6 +31,18 @@ public IntelliSenseOptionPageControl(IServiceProvider serviceProvider) : base(se
BindToOption(Always_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Always, LanguageNames.CSharp);
}
private void Show_completion_list_after_a_character_is_typed_Checked(object sender, RoutedEventArgs e)
{
Show_completion_list_after_a_character_is_deleted.IsEnabled = Show_completion_list_after_a_character_is_typed.IsChecked == true;
}
private void Show_completion_list_after_a_character_is_typed_Unchecked(object sender, RoutedEventArgs e)
{
Show_completion_list_after_a_character_is_deleted.IsEnabled = Show_completion_list_after_a_character_is_typed.IsChecked == true;
Show_completion_list_after_a_character_is_deleted.IsChecked = false;
Show_completion_list_after_a_character_is_deleted_Unchecked(sender, e);
}
private void Show_completion_list_after_a_character_is_deleted_Checked(object sender, RoutedEventArgs e)
{
this.OptionService.SetOptions(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册