AvalonEdit 是一个基于 WPF 的文本编辑器组件。它是由 Daniel Grunwald 为 SharpDevelop 编写的。从 5.0 版开始,AvalonEdit 根据MIT许可证发布。这个控件具有强大的代码高亮显示功能,支持多种不同的编程语言的语法高亮。同时,它也提供了智能提示、代码折叠等功能,使得代码编辑更为便捷。你可以通过NuGet安装AvalonEdit,并在你的WPF应用程序中使用它。
<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 的命名空间,属于硬编码。
pack://application:,,,/{程序集名称};component/Resources/#JetBrains Mono其中,{程序集名称} 需要替换为你自己的应用程序信息。
using ICSharpCode.AvalonEdit; using Microsoft.Xaml.Behaviors; using System; using System.Windows; public sealed class AvalonEditBehaviour : Behavior<TextEditor> { // 堆代码 duidaima.com 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>
ICSharpCode.AvalonEdit.Search.SearchPanel.Install(TextEditor);以上代码在 XAML 的后置代码构造函数中 InitializeComponent 方法后调用即可。
<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; } }