Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions CS/CodeEditor/Docs/CodeEditor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# CodeEditor

WPF control that embeds Monaco Editor (VS Code editor) using WebView2 for code editing with syntax highlighting.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

## Properties

| Name | Type | Description |
| ---- | ---- | ----------- |
| `Text` | `string` | Gets or sets editor text. This is a dependency property. Supports two-way binding. |
Comment thread
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. |
Comment thread
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` |
Comment thread
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` |
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated
| `WordWrap` | `EditorWordWrap` | Gets or sets word wrap mode. This is a dependency property. Default: `EditorWordWrap.Off` |
Comment thread
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` |
Comment thread
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` |
Comment thread
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 Monarch tokenizer. |
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated
| `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 |
21 changes: 21 additions & 0 deletions CS/CodeEditor/Docs/CodeEditorService.md
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 Monarch tokenizer in the associated `CodeEditor`. |
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated
292 changes: 292 additions & 0 deletions CS/CodeEditor/Docs/Overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
## Introduction

`CodeEditor` is a WPF control that embeds the [Monaco Editor](https://microsoft.github.io/monaco-editor/) (the editor engine used by Visual Studio Code) using [Microsoft WebView2](https://learn.microsoft.com/en-us/microsoft-edge/webview2/).
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

The editor includes modern code editing capabilities — syntax highlighting, folding, minimap, theming, and custom languages — within WPF applications.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

The primary editing surface is the `CodeEditor` control, which exposes a focused, WPF-friendly API.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

The library also includes:
Comment thread
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.
Comment thread
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.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

> **Supported Monaco version:** 0.55.1
> The control is built and validated against this specific release.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

## Prerequisites

- Windows with [Microsoft Edge WebView2 Runtime](https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution)
- DevExpress WPF **26.1** (or newer compatible version)

The required .NET version depends on the DevExpress WPF version in use.
See DevExpress documentation:
[WPF Controls → Prerequisites → .NET / .NET Core](https://docs.devexpress.com/WPF/8091/prerequisites#netnet-core)
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

> 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 any of the standard Monaco themes:
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

```csharp
editor.ThemeName = "vs";
editor.ThemeName = "vs-dark";
editor.ThemeName = "hc-black";
```

These themes are provided by Monaco.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

### DevExpress Theme Integration

By default, `CodeEditor` does not automatically track DevExpress theme changes.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

To synchronize Monaco with the active DevExpress theme, attach `ThemeBehavior`:
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

```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`:
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

- Detects the current DevExpress theme
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated
- 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

The theme is updated automatically when the DevExpress theme changes.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

### 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 specific token types (such as `keyword`, `comment`, `string`, and other) are rendered.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

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.
Comment thread
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 the syntax highlighting rules.
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

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 topic for additional information: [Monarch Documentation](https://microsoft.github.io/monaco-editor/monarch.html)
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

### Language Configuration

The optional `Configuration` property defines editor behavior such as:
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

- Line and block comments
- Brackets
- Auto-closing pairs
- Surrounding pairs

The configuration must also be provided as a JavaScript object literal.

For language configuration details (brackets, comments, auto-closing pairs, etc.),
refer to the following topic: [Language Configuration Guide](https://code.visualstudio.com/api/language-extensions/language-configuration-guide)
Comment thread
sergepilipchuk marked this conversation as resolved.
Outdated

## 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)
Loading
Loading