-
Notifications
You must be signed in to change notification settings - Fork 1
Add documentation for CodeEditor control #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sergepilipchuk
merged 5 commits into
DevExpress-Examples:26.1.1+
from
sergepilipchuk:sp-add-doc-26.1.1+
Jun 29, 2026
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
1cac576
Add documentation for CodeEditor control
sergepilipchuk 3b39c07
Update theming snippet in Overview docs
sergepilipchuk 0e34f8f
Update CodeEditor docs formatting and wording
sergepilipchuk 32486ca
Apply suggestions from code review
sergepilipchuk 5b827b0
Apply suggestions from code review
sergepilipchuk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # CodeEditor | ||
|
|
||
| WPF code editor control with syntax highlighting and other modern code display/navigation capabilities. This control embeds Monaco Editor (Visual Studio Code editor) using WebView2. | ||
|
|
||
| ## Properties | ||
|
|
||
| | Name | Type | Description | | ||
| | ---- | ---- | ----------- | | ||
| | `Text` | `string` | Gets or sets the editor text. This is a dependency property. Supports two-way binding. | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `EditorLanguage` | `string` | Gets or sets the programming language for syntax highlighting. This is a dependency property. Default: `"csharp"` | | ||
| | `ReadOnly` | `bool` | Gets or sets whether the editor is read-only. This is a dependency property. Default: `false` | | ||
| | `IsModified` | `bool` | Gets whether the content has been modified since the last save. This is a readonly dependency property. | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `ShowLineNumbers` | `bool` | Gets or sets whether line numbers are displayed. This is a dependency property. Default: `true` | | ||
| | `LineNumbersMinChars` | `int` | Gets or sets the minimum number of character slots reserved for the line-number gutter. This is a dependency property. Default: `5` | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `ShowMinimap` | `bool` | Gets or sets whether the minimap is displayed. This is a dependency property. Default: `false` | | ||
| | `ShowGlyphMargin` | `bool` | Gets or sets whether the glyph margin is displayed. This is a dependency property. Default: `false` | | ||
| | `EnableFolding` | `bool` | Gets or sets whether code folding is enabled. This is a dependency property. Default: `true` | | ||
| | `TabSize` | `int` | Gets or sets the tab size in spaces (1-64). This is a dependency property. Default: `4` | | ||
| | `InsertSpaces` | `bool` | Gets or sets whether spaces are inserted instead of tabs. This is a dependency property. Default: `true` | | ||
| | `DetectIndentation` | `bool` | Gets or sets whether indentation is detected from file content. This is a dependency property. Default: `true` | | ||
| | `AutoIndent` | `EditorAutoIndent` | Gets or sets auto-indentation mode. This is a dependency property. Default: `EditorAutoIndent.Full` | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `WordWrap` | `EditorWordWrap` | Gets or sets word wrap mode. This is a dependency property. Default: `EditorWordWrap.Off` | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `EnableScrollBeyondLastLine` | `bool` | Gets or sets whether scrolling beyond the last line is allowed. This is a dependency property. Default: `true` | | ||
| | `ScrollBeyondLastColumn` | `int` | Gets or sets the number of columns to scroll beyond the last character. This is a dependency property. Default: `5` | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `EnableSmoothScrolling` | `bool` | Gets or sets whether smooth scrolling is enabled. This is a dependency property. Default: `false` | | ||
| | `EnableStickyScroll` | `bool` | Gets or sets whether sticky scroll is enabled. This is a dependency property. Default: `true` | | ||
| | `EnableContextMenu` | `bool` | Gets or sets whether the context menu is enabled. This is a dependency property. Default: `true` | | ||
| | `EnableDragAndDrop` | `bool` | Gets or sets whether drag and drop is enabled. This is a dependency property. Default: `true` | | ||
| | `EnableMouseWheelZoom` | `bool` | Gets or sets whether zooming with <kbd>Ctrl</kbd>+<kbd>MouseWheel</kbd> is enabled. This is a dependency property. Default: `false` | | ||
| | `EnableQuickSuggestions` | `bool` | Gets or sets whether quick suggestions are enabled. This is a dependency property. Default: `true` | | ||
| | `EnableWordBasedSuggestions` | `bool` | Gets or sets whether word-based suggestions are enabled. This is a dependency property. Default: `true` | | ||
| | `EnableSuggestOnTriggerCharacters` | `bool` | Gets or sets whether suggestions appear automatically when typing trigger characters. This is a dependency property. Default: `true` | | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
| | `EnableParameterHints` | `bool` | Gets or sets whether parameter hints are displayed. This is a dependency property. Default: `true` | | ||
| | `ThemeName` | `string` | Gets or sets the Monaco Editor theme name. This is a dependency property. Default: `"vs"` | | ||
| | `MarkAsSavedCommand` | `ICommand` | Gets the command that resets the `IsModified` flag. | | ||
|
|
||
| ## Methods | ||
|
|
||
| | Name | Description | | ||
| | ---- | ----------- | | ||
| | `GetAvailableLanguagesAsync(CancellationToken)` | Asynchronously retrieves a list of available programming language IDs. | | ||
| | `RegisterLanguage(LanguageDescriptor)` | Registers a custom programming language with a Monarch tokenizer. | | ||
| | `RegisterTheme(MonacoTheme)` | Registers a custom Monaco Editor theme. | | ||
| | `MarkAsSaved()` | Resets the `IsModified` property to `false`. | | ||
| | `Dispose()` | Releases WebView2 resources. | | ||
|
|
||
| ## Events | ||
|
|
||
| | Name | Description | | ||
| | ---- | ----------- | | ||
| | `EditorInitialized` | Occurs when the Monaco Editor is fully initialized and ready for commands. | | ||
|
|
||
| ## Enums | ||
|
|
||
| ### EditorAutoIndent | ||
|
|
||
| | Member | Description | | ||
| | ------ | ----------- | | ||
| | `None` | No automatic indentation | | ||
| | `Keep` | Keep current indentation | | ||
| | `Brackets` | Indent based on brackets | | ||
| | `Advanced` | Advanced indentation | | ||
| | `Full` | Full automatic indentation (recommended) | | ||
|
|
||
| ### EditorWordWrap | ||
|
|
||
| | Member | Description | | ||
| | ------ | ----------- | | ||
| | `Off` | No word wrapping | | ||
| | `On` | Word wrapping enabled | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # CodeEditorService | ||
|
|
||
| MVVM service that provides access to CodeEditor control functionality from ViewModels. | ||
|
|
||
| ## Interface | ||
|
|
||
| ```csharp | ||
| public interface ICodeEditorService { | ||
| void MarkAsSaved(); | ||
| Task<IReadOnlyCollection<string>> GetLanguagesAsync(CancellationToken cancellationToken = default); | ||
| void RegisterLanguage(LanguageDescriptor language); | ||
| } | ||
| ``` | ||
|
|
||
| ## Methods | ||
|
|
||
| | Name | Description | | ||
| | ---- | ----------- | | ||
| | `MarkAsSaved()` | Resets the `IsModified` flag of the associated `CodeEditor` to `false`. | | ||
| | `GetLanguagesAsync(CancellationToken)` | Asynchronously retrieves a collection of available programming language IDs from the associated `CodeEditor`. | | ||
| | `RegisterLanguage(LanguageDescriptor)` | Registers a custom programming language with a Monarch tokenizer in the associated `CodeEditor`. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,287 @@ | ||
| ## Introduction | ||
|
|
||
| This DevExpress WPF example can display code using a specially-designed `CodeEditor` control. This control is a wrapper around the [Monaco Editor](https://microsoft.github.io/monaco-editor/) used by Visual Studio Code. This advanced editor supports numerous modern code editing capabilities such as syntax highlighting, region folding, minimap, theming, and custom language support. Since **Monaco Editor** is a web control, our WPF wrapper uses [Microsoft WebView2](https://learn.microsoft.com/en-us/microsoft-edge/webview2/) to display it. | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| Our `CodeEditor` control implementation uses the following helper classes: | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
|
|
||
| - `ThemeBehavior` - integrates Monaco with DevExpress themes. | ||
| - `CodeEditorService` - a lightweight service for cases where direct interaction with the control is not sufficient. | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
|
|
||
| The control is designed as a **state-driven wrapper**: WPF owns the editor state through dependency properties, and Monaco reflects that state while propagating changes back to WPF in an MVVM-friendly way. | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| ## Prerequisites | ||
|
|
||
| - DevExpress WPF v26.1 (or newer compatible version) | ||
| - Monaco Editor v0.55.1 (the control is built and validated against this specific release) | ||
| - .NET version compatible with DevExpress WPF version you use: [WPF Controls → Prerequisites → .NET / .NET Core](https://docs.devexpress.com/WPF/8091/prerequisites#netnet-core) | ||
| - Windows with [Microsoft Edge WebView2 Runtime](https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution) | ||
|
|
||
| > The `CodeEditor` project must be compiled against the same DevExpress WPF version that is used in the consuming application. | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### 1. Add the `CodeEditor` project | ||
|
|
||
| Add the `CodeEditor` project to your solution and reference it from your WPF application: | ||
|
|
||
| - Add existing project → `CodeEditor` | ||
| - Add project reference from your WPF app | ||
| - Ensure DevExpress WPF and WebView2 dependencies are resolved | ||
|
|
||
| ### 2. Declare the XML namespace | ||
|
|
||
| ```xml | ||
| <Window | ||
| x:Class="YourApp.MainWindow" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:ce="clr-namespace:CodeEditor;assembly=CodeEditor"> | ||
|
|
||
| <Grid> | ||
| <ce:CodeEditor | ||
| Text="{Binding Code, Mode=TwoWay}" | ||
| EditorLanguage="csharp" | ||
| ThemeName="vs-dark" /> | ||
| </Grid> | ||
|
|
||
| </Window> | ||
| ``` | ||
|
|
||
| ### 3. Create a ViewModel | ||
|
|
||
| ```csharp | ||
| using DevExpress.Mvvm; | ||
|
|
||
| public class MainViewModel : BindableBase | ||
| { | ||
| private string _code = @"using System; | ||
|
|
||
| class Program | ||
| { | ||
| static void Main() | ||
| { | ||
| Console.WriteLine(""Hello, Monaco!""); | ||
| } | ||
| }"; | ||
|
|
||
| public string Code | ||
| { | ||
| get => _code; | ||
| set => SetProperty(ref _code, value); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Set the `DataContext` of the window to an instance of `MainViewModel`. | ||
|
|
||
| The editor content is automatically synchronized with the bound property. | ||
|
|
||
| > **Note:** | ||
| > `CodeEditor` does not automatically track DevExpress theme changes. | ||
| > To synchronize Monaco with the active DevExpress theme, use `ThemeBehavior`. | ||
|
|
||
| ## Theming | ||
|
|
||
| `CodeEditor` supports built-in Monaco themes, DevExpress theme integration, and custom theme registration. | ||
|
|
||
| ### Built-in Monaco Themes | ||
|
|
||
| You can use standard Monaco themes: | ||
|
|
||
| ```csharp | ||
| editor.ThemeName = "vs"; | ||
| editor.ThemeName = "vs-dark"; | ||
| editor.ThemeName = "hc-black"; | ||
| ``` | ||
|
|
||
|
|
||
|
|
||
| ### DevExpress Theme Integration | ||
|
|
||
|
|
||
|
|
||
| To synchronize a Monaco Editor with the active DevExpress theme, attach a `ThemeBehavior`: | ||
|
|
||
| ```xml | ||
| xmlns:ce="clr-namespace:CodeEditor;assembly=CodeEditor" | ||
| xmlns:cet="clr-namespace:CodeEditor.Theming;assembly=CodeEditor" | ||
| xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" | ||
|
|
||
| ... | ||
|
|
||
| <ce:CodeEditor | ||
| Text="{Binding Code}" | ||
| EditorLanguage="csharp"> | ||
|
|
||
| <dxmvvm:Interaction.Behaviors> | ||
| <cet:ThemeBehavior ApplyDevExpressColors="True" /> | ||
| </dxmvvm:Interaction.Behaviors> | ||
|
|
||
| </ce:CodeEditor> | ||
| ``` | ||
|
|
||
| `ThemeBehavior` synchronizes DevExpress themes and Monaco Editor appearance in the following manner: | ||
|
|
||
| - Detects the current DevExpress theme at startup and each time the theme changes | ||
| - Resolves Light / Dark / High Contrast base | ||
| - Registers and applies a corresponding Monaco theme | ||
| - Optionally maps DevExpress palette colors to Monaco color keys via the `ApplyDevExpressColors` property | ||
|
|
||
|
|
||
|
|
||
| ### Custom Themes | ||
|
|
||
| You can register a custom Monaco theme programmatically: | ||
|
|
||
| ```csharp | ||
| var theme = new MonacoTheme | ||
| { | ||
| Name = "my-theme", | ||
| Base = MonacoThemeBase.Dark, | ||
| Colors = new Dictionary<string, Color> | ||
| { | ||
| ["editor.background"] = Color.FromRgb(30, 30, 30), | ||
| ["editor.foreground"] = Color.FromRgb(220, 220, 220) | ||
| } | ||
| }; | ||
|
|
||
| editor.RegisterTheme(theme); | ||
| editor.ThemeName = "my-theme"; | ||
| ``` | ||
|
|
||
| For a complete list of commonly used Monaco theme color keys, see the official VS Code theme color reference (Monaco uses the same keys): [Theme Color](https://code.visualstudio.com/api/references/theme-color). | ||
|
|
||
| ### Rules | ||
|
|
||
| In addition to UI colors, Monaco themes support token-level styling via `Rules`. | ||
|
|
||
| Rules define how the editor renders specific token types such as `keyword`, `comment`, `string`, and others. | ||
|
|
||
| You can use `Rules` to override the appearance of existing token types or to define styling for custom tokens introduced by a custom language definition. | ||
|
|
||
| ```csharp | ||
| var theme = new MonacoTheme | ||
| { | ||
| Name = "my-theme", | ||
| Base = MonacoThemeBase.Dark, | ||
| Rules = new[] | ||
| { | ||
| new MonacoThemeRule | ||
| { | ||
| Token = "keyword", | ||
| Foreground = Color.FromRgb(86, 156, 214), | ||
| FontStyle = MonacoFontStyle.Bold | ||
| }, | ||
| new MonacoThemeRule | ||
| { | ||
| Token = "comment", | ||
| Foreground = Color.FromRgb(106, 153, 85), | ||
| FontStyle = MonacoFontStyle.Italic | ||
| } | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| `Rules` is an init-only property and must be provided during theme initialization. | ||
|
|
||
| If you use `ThemeBehavior`, token styling can also be supplied through its `Rules` property, and it allows rule customization alongside DevExpress theme integration. | ||
|
|
||
| ## Languages | ||
|
|
||
| `CodeEditor` supports both built-in Monaco languages and custom language registration. | ||
|
|
||
| ### Built-in Languages | ||
|
|
||
| To use a built-in Monaco language, specify the `EditorLanguage` property: | ||
|
|
||
| ```csharp | ||
| editor.EditorLanguage = "csharp"; | ||
| editor.EditorLanguage = "javascript"; | ||
| editor.EditorLanguage = "json"; | ||
| ``` | ||
|
|
||
| The value must match a language ID supported in Monaco Editor. | ||
|
sergepilipchuk marked this conversation as resolved.
Outdated
|
||
|
|
||
| ### Custom Languages | ||
|
|
||
| You can register custom languages using `LanguageDescriptor`: | ||
|
|
||
| ```csharp | ||
| var language = new LanguageDescriptor | ||
| { | ||
| Id = "mylang", | ||
|
|
||
| Monarch = @"{ | ||
| tokenizer: { | ||
| root: [ | ||
| [/\b(if|else|while)\b/, 'keyword'], | ||
| [/\/\/.*$/, 'comment'], | ||
| [/"".*?""/, 'string'], | ||
| [/\d+/, 'number'] | ||
| ] | ||
| } | ||
| }", | ||
|
|
||
| Configuration = @"{ | ||
| comments: { | ||
| lineComment: '//' | ||
| }, | ||
| brackets: [ | ||
| ['{', '}'], | ||
| ['[', ']'], | ||
| ['(', ')'] | ||
| ] | ||
| }" | ||
| }; | ||
|
|
||
| editor.RegisterLanguage(language); | ||
| editor.EditorLanguage = "mylang"; | ||
| ``` | ||
|
|
||
| ### Monarch Definition | ||
|
|
||
| The `Monarch` property defines syntax highlighting rules. | ||
|
|
||
| The property must contain a valid Monaco Monarch tokenizer definition specified as a JavaScript object literal. | ||
|
|
||
| All standard Monarch features are supported: | ||
|
|
||
| - Multiple states | ||
| - Nested states | ||
| - Regular expressions | ||
| - Rule objects | ||
| - Includes and state transitions | ||
|
|
||
| Refer to the following help topic for additional information: [Monarch Documentation](https://microsoft.github.io/monaco-editor/monarch.html) | ||
|
|
||
| ### Language Configuration | ||
|
|
||
| The optional `Configuration` property defines editor behavior attributes such as: | ||
|
|
||
| - Line and block comments | ||
| - Brackets | ||
| - Auto-closing pairs | ||
| - Surrounding pairs | ||
|
|
||
| The configuration must also be provided as a JavaScript object literal. | ||
|
|
||
| For additional information, refer to the following help topic: [Language Configuration Guide](https://code.visualstudio.com/api/language-extensions/language-configuration-guide) | ||
|
|
||
| ## See also | ||
|
|
||
| ### API Reference | ||
|
|
||
| - [CodeEditor API Reference](CodeEditor.md) | ||
| - [CodeEditorService API Reference](CodeEditorService.md) | ||
| - [ThemeBehavior API Reference](ThemeBehavior.md) | ||
|
|
||
| ### Monaco Resources | ||
|
|
||
| - [Monaco Editor](https://microsoft.github.io/monaco-editor/) | ||
| - [Monarch Documentation](https://microsoft.github.io/monaco-editor/monarch.html) | ||
| - [Monaco Playground – Custom Languages Example](https://microsoft.github.io/monaco-editor/playground.html?source=v0.55.1#example-extending-language-services-custom-languages) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.