基于AvalonEdit和prism的文本编辑器
第一步:导入AvalonEdit包

第二步:编辑AvalonEditBehaviour
我们可以通过 TextEditor 的 Text 属性来获取或设置代码编辑器中的内容,但该属性不是一个依赖属性,所以我们不能直接将其绑定到 ViewModel 上。
using ICSharpCode.AvalonEdit;
using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;namespace WPF_AvalonEdit
{public sealed class AvalonEditBehaviour : Behavior{//依赖属性绑定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;}}}}}
第三步:编写界面xaml
第四步:编写后台工具类
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Folding;
using System;
using System.Windows;
using System.Windows.Input;namespace WPF_AvalonEdit.Views
{/// /// Interaction logic for MainWindow.xaml/// public partial class MainWindow : Window{public MainWindow(){InitializeComponent();//代码折叠功能foldingManager = FoldingManager.Install(TextEditor.TextArea);//开启快速搜索框 快捷键"CTRL + F"ICSharpCode.AvalonEdit.Search.SearchPanel.Install(TextEditor);}FoldingManager foldingManager = null;XmlFoldingStrategy foldingStrategy = new XmlFoldingStrategy();private void CodeEditor_TextChanged(object sender, EventArgs e){if (foldingManager == null) return;foldingStrategy.UpdateFoldings(foldingManager, TextEditor.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;}}//ctrl+鼠标滚轮实现文字的放大和缩小private void TextEditor_PreviewMouseWheel(object sender, MouseWheelEventArgs e){double scale = (sender as TextEditor).FontSize;if (Keyboard.IsKeyDown(Key.LeftCtrl)){if (e.Delta < 0){scale -= 1;}else{scale += 1;}this.TextEditor.FontSize = scale;}}}
}
第四步:绑定事件和属性
using Prism.Commands;
using Prism.Mvvm;namespace WPF_AvalonEdit.ViewModels
{public class MainWindowViewModel : BindableBase{public MainWindowViewModel(){}private string _Code;public string Code{get { return _Code; }set { SetProperty(ref _Code, value); }}private string _text;public string text{get { return _text; }set { SetProperty(ref _text, value); }}public DelegateCommand setCmd => new DelegateCommand(() =>{Code = text;});public DelegateCommand getCmd => new DelegateCommand(() =>{text = Code;});}
}
展示效果

2023/3/12