AvalonEdit_文本编辑器
基于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<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;
}
}
}
}
}
第三步:编写界面xaml
<Window
x:Class="WPF_AvalonEdit.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:prism="http://prismlibrary.com/"
Title="文本编辑器示例程序"
Width="525"
Height="350"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<avalonEdit:TextEditor
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
x:Name="TextEditor"
FontFamily="Consolas"
FontSize="16px"
LineNumbersForeground="Black"
PreviewMouseWheel="TextEditor_PreviewMouseWheel"
ShowLineNumbers="True"
SyntaxHighlighting="XML"
TextChanged="CodeEditor_TextChanged"
WordWrap="True">
<i:Interaction.Behaviors>
<bh:AvalonEditBehaviour xmlns:bh="clr-namespace:WPF_AvalonEdit" CodeText="{Binding Code}" />
</i:Interaction.Behaviors>
</avalonEdit:TextEditor>
<StackPanel Grid.Row="1">
<Button Command="{Binding setCmd}" Content="刷新数据" />
<Button Command="{Binding getCmd}" Content="获取数据" />
<TextBox Text="{Binding text}" Height="129" />
</StackPanel>
</Grid>
</Window>
第四步:编写后台工具类
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Folding;
using System;
using System.Windows;
using System.Windows.Input;
namespace WPF_AvalonEdit.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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