• WPF学习笔记(四):AvalonEdit 代码高亮编辑控件专题


    AvalonEdit 是一个基于 WPF 的文本编辑器组件。它是由 Daniel GrunwaldSharpDevelop 编写的。从 5.0 版开始,AvalonEdit 根据MIT许可证发布。

    通过使用 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 “ 打开一个快速搜索框,要搜索的文字会高亮显示,同时支持对搜索结果进行导航:
    ILSpy 的快速搜索功能
    事实上 ILSpy 使用的也是 AvalonEdit 控件,开启搜索面板仅需一行代码:

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

    以上代码在 XAML 的后置代码构造函数中 InitializeComponent 方法后调用即可。

    代码折叠功能

    代码折叠是一些文本编辑器,源代码编辑器和IDE的一个功能,它允许用户有选择地隐藏和显示 – “折叠” – 当前编辑文件的各个部分作为例行编辑操作的一部分。 这允许用户管理大量文本,同时仅查看在任何给定时间特别相关的文本子部分。
    路遥工具箱的代码折叠功能
    针对 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;
        }
    }
    

    结束

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

  • 相关阅读:
    windows bat
    如何重置postgresql用户密码
    SQL Server如何修改登录密码
    MySQL操作题(mysql_V20190307)
    MariaDB主从备份
    MySQL&MariaDB数据库备份脚本
    SQL语句大全,所有的SQL都在这里
    数据库操作语句大全(sql)
    Python代码,将图片转为了Excel
    亚晨yacn软件config数据获取
  • 原文地址:https://www.cnblogs.com/Soar1991/p/15834391.html
Copyright © 2020-2023  润新知