天天看點

WPF學習筆記(四):AvalonEdit 代碼高亮編輯控件專題

AvalonEdit 是一個基于 WPF 的文本編輯器元件。它是由 Daniel Grunwald 為 SharpDevelop 編寫的。從 5.0 版開始,AvalonEdit 根據MIT許可證釋出。

WPF學習筆記(四):AvalonEdit 代碼高亮編輯控件專題
通過使用 AvalonEdit ,小夥伴們可以很容易的在自己的程式中內建代碼編輯器。AvalonEdit 在路遙工具箱中有着廣泛的運用。

安裝 AvalonEdit

首先,通過 NuGet 安裝 AvalonEdit ,位址是:https://www.nuget.org/packages/AvalonEdit 。

接着将以下代碼粘貼到 XAML 檔案中,即可建立一個最簡單的 AvalonEdit 控件:

<avalonEdit:TextEditor
    xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
    Name="TextEditor"
    SyntaxHighlighting="C#"
    FontFamily="Consolas"
    FontSize="10pt" 
    LineNumbersForeground="Black" 
    ShowLineNumbers="True">
</avalonEdit:TextEditor>
           

第二行的

xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"

是 AvalonEdit 的命名空間,屬于寫死。

AvalonEdit 内置了多種文法高亮規則,

SyntaxHighlighting="C#"

的意思是對 C# 進行代碼高亮。如果需要對 XML 代碼進行高亮,僅需将 C# 改為 XML 即可:

SyntaxHighlighting="XML"

第九行的

ShowLineNumbers="True"

代表展示每行的行号,這在展示單行過長的文字時非常有用,預設為 False 。

使用 JetBrand Mono 字型展示代碼

JetBrand Mono 字型非常适合用來展示代碼,且該字型檔案非常小巧(僅有 200K 左右),可以直接嵌入在應用中。

首先,将下載下傳到的 JetBrand Mono 字型檔案 JetBrainsMono.ttf 複制到項目的 Resources 檔案夾,設定檔案的”生成操作“為”資源“。

接着設定 TextEditor 的 FontFamily 屬性即可:

pack://application:,,,/{程式集名稱};component/Resources/#JetBrains Mono
           

其中,

{程式集名稱}

需要替換為你自己的應用程式資訊。

對 AvalonEdit 進行 MVVM 綁定

我們可以通過 TextEditor 的 Text 屬性來擷取或設定代碼編輯器中的内容,但該屬性不是一個依賴屬性,是以我們不能直接将其綁定到 ViewModel 上。

一個針對 AvalonEdit 的 Behavior 可以協助解決該問題:

using ICSharpCode.AvalonEdit;
using Microsoft.Xaml.Behaviors;
using System;
using System.Windows;

public sealed class AvalonEditBehaviour : Behavior<TextEditor>
{
    public static readonly DependencyProperty CodeTextProperty =
        DependencyProperty.Register("CodeText", typeof(string), typeof(AvalonEditBehaviour),
        new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PropertyChangedCallback));

    public string CodeText
    {
        get { return (string)GetValue(CodeTextProperty); }
        set { SetValue(CodeTextProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        if (AssociatedObject != null)
            AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        if (AssociatedObject != null)
            AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
    }

    private void AssociatedObjectOnTextChanged(object sender, EventArgs eventArgs)
    {
        if (sender is TextEditor textEditor)
        {
            if (textEditor.Document != null)
                CodeText = textEditor.Document.Text;
        }
    }

    private static void PropertyChangedCallback(
        DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        var behavior = dependencyObject as AvalonEditBehaviour;
        if (behavior.AssociatedObject != null)
        {
            var editor = behavior.AssociatedObject;
            if (editor.Document != null)
            {
                var caretOffset = editor.CaretOffset;
                editor.Document.Text = dependencyPropertyChangedEventArgs.NewValue.ToString();
                if (caretOffset <= editor.Document.Text.Length) editor.CaretOffset = caretOffset;
            }
        }
    }
}
           

假設上述代碼存在于 Behaviors 命名空間下,且 ViewModel 有一個名為 Code 的通知屬性。則 XAML 代碼如下:

<avalonEdit:TextEditor xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit">
     <i:Interaction.Behaviors xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
         <bh:AvalonEditBehaviour xmlns:bh="clr-namespace:Behaviors"  CodeText="{Binding Code}"/>                
     </i:Interaction.Behaviors>
 </avalonEdit:TextEditor>
           

開啟快速搜尋框

在使用 ILSpy 檢視程式集源代碼時,可以通過快捷鍵 ” CTRL + F “ 打開一個快速搜尋框,要搜尋的文字會高亮顯示,同時支援對搜尋結果進行導航:

WPF學習筆記(四):AvalonEdit 代碼高亮編輯控件專題

ILSpy 的快速搜尋功能

事實上 ILSpy 使用的也是 AvalonEdit 控件,開啟搜尋面闆僅需一行代碼:

ICSharpCode.AvalonEdit.Search.SearchPanel.Install(TextEditor);
           

以上代碼在 XAML 的後置代碼構造函數中

InitializeComponent

方法後調用即可。

代碼折疊功能

代碼折疊是一些文本編輯器,源代碼編輯器和IDE的一個功能,它允許使用者有選擇地隐藏和顯示 – “折疊” – 目前編輯檔案的各個部分作為例行編輯操作的一部分。 這允許使用者管理大量文本,同時僅檢視在任何給定時間特别相關的文本子部分。

WPF學習筆記(四):AvalonEdit 代碼高亮編輯控件專題

路遙工具箱的代碼折疊功能

針對 XML 語言的代碼折疊,需要用到 FlodingManager 和 XmlFoldingStrategy 。

<avalonedit:TextEditor SyntaxHighlighting="XML" TextChanged="CodeEditor_TextChanged" ShowLineNumbers="True" WordWrap="True" x:Name="CodeEditor">
    <avalonedit:TextEditor.ContextMenu>
        <ContextMenu>
            <MenuItem Header="全部折疊" x:Name="CloseMenuItem" Click="CloseMenuItem_Click"></MenuItem>
            <MenuItem Header="全部展開" x:Name="OpenMenuItem" Click="OpenMenuItem_Click"></MenuItem>
        </ContextMenu>
    </avalonedit:TextEditor.ContextMenu>
</avalonedit:TextEditor>
           

對應的後置代碼如下:

using ICSharpCode.AvalonEdit.Folding;
using System;
using System.Windows;
using System.Windows.Controls;

public MyUserControl() //構造函數
{
    InitializeComponent();
    foldingManager = FoldingManager.Install(CodeEditor.TextArea);
}

FoldingManager foldingManager = null;
XmlFoldingStrategy foldingStrategy = new XmlFoldingStrategy();

private void CodeEditor_TextChanged(object sender, EventArgs e)
{
    if (foldingManager == null) return;
    foldingStrategy.UpdateFoldings(foldingManager, CodeEditor.Document);
}
private void CloseMenuItem_Click(object sender, RoutedEventArgs e)
{
    if (foldingManager == null) return;
    var isFrist = true;
    foreach (var item in foldingManager.AllFoldings)
    {
        if (isFrist)
        {
            isFrist = false;
            continue;
        }
        item.IsFolded = true;
    }
}
private void OpenMenuItem_Click(object sender, RoutedEventArgs e)
{
    if (foldingManager == null) return;
    foreach (var item in foldingManager.AllFoldings)
    {
        item.IsFolded = false;
    }
}
           

結束

以上就是本片的全部内容,本文展示的所有代碼均可以在路遙工具箱中找到運用。

歡迎來到:碼農很忙 。