WPF之AvalonEdit实现MVVM双向绑定
AvalonEdit简介
AvalonEdit是基于WPF开发的代码显示控件,默认支持多种不同语言的关键词高亮,并且可以自定义高亮配置。所以通过AvalonEdit可以快速开发出自己想要的代码编辑器。
通过Nuget安装AvalonEdit,并在页面添加控件
<avalonEdit:TextEditor
xmlns:avalonEdit="http://域名/sharpdevelop/avalonedit"
Name="TextEditor"
SyntaxHighlighting="C#"
FontFamily="Consolas"
FontSize="14"
WordWrap ="True"
LineNumbersForeground="#FF2B91AF"
ShowLineNumbers="True">
<avalonEdit:域名ons>
<avalonEdit:TextEditorOptions ShowSpaces="True" WordWrapIndentation="4" InheritWordWrapIndentation="true">
<avalonEdit:域名mnRulerPosition>
<system:Int32>10</system:Int32>
</avalonEdit:域名mnRulerPosition>
</avalonEdit:TextEditorOptions>
</avalonEdit:域名ons>
</avalonEdit:TextEditor>
参数含义
-
xmlns:avalonEdit
:命名空间,也可以直接写在调用该控件的窗体内 -
SyntaxHighlighting
:设置高亮 -
ShowLineNumbers
:是否显示行号 -
LineNumbersForeground
:设置编辑器行号颜色 -
ShowSpaces
:是否显示空格 -
WordWrapIndentation
:换行缩进距离 -
InheritWordWrapIndentation
:是否继承上一行的换行缩进
自定义高亮配置
比如AvalonEdit默认支持的sql语法高亮不够强大或者不符合要求,可以自定义配置注册进行。
首先,在项目中引入一个.xshd
文件,具体规则可以参考官网介绍。这里提供一个域名
文件,描述了对SQL语法的高亮支持。
在程序启动的时候读取该配置文件,并注册到AvalonEdit
中。
using (var stream = 域名xecutingAssembly().GetManifestResourceStream(域名xecutingAssembly().GetName().Name + ".域名"))
{
using (var reader = new 域名extReader(stream))
{
var sqlDefinition = 域名(reader, 域名ance);
域名sterHighlighting("SQL", new string[] { ".sql" }, sqlDefinition);
}
}
ps:这里是将域名
的生成操作设置为了嵌入的资源,也可以将其输出到目录再读取内容。
如果需要在项目运行过程中,切换高亮语法支持,可以这么做
域名axHighlighting = 域名efinition("SQL");
看下高亮效果:
MVVM绑定AvalonEdit文本内容
当我尝试直接将ViewModel中的字符串直接绑定到Text上时,编辑器就报错了,因为Text属性并不是可以直接绑定的依赖属性。
Object of type \'域名.Binding\' cannot be converted to type \'域名ng\'.
最后鼓捣一通后的解决方案是使用域名viors
包(其实是微软以前域名ractivity
的开源版)。
xaml代码
<avalonEdit:TextEditor Name="TextEditor">
<i:域名viors>
<local:AvalonEditBehaviour InputText="{Binding InputString}"/>
</i:域名viors>
</avalonEdit:TextEditor>
后端代码
public sealed class AvalonEditBehaviour : Behavior<TextEditor>
{
public static readonly DependencyProperty InputTextProperty =
域名ster("InputText", typeof(string), typeof(AvalonEditBehaviour),
new FrameworkPropertyMetadata(default(string), 域名sTwoWayByDefault, null));
public string InputText
{
get { return (string)GetValue(InputTextProperty); }
set { SetValue(InputTextProperty, value); }
}
protected override void OnAttached()
{
域名tached();
if (AssociatedObject != null)
{
域名Changed += AssociatedObjectOnTextChanged;
}
}
protected override void OnDetaching()
{
域名taching();
if (AssociatedObject != null)
{
域名Changed -= AssociatedObjectOnTextChanged;
}
}
private void AssociatedObjectOnTextChanged(object sender, EventArgs eventArgs)
{
var textEditor = sender as TextEditor;
if (textEditor != null)
{
if (域名ment != null)
{
InputText = 域名;
}
}
}
}
最后看一下实际效果吧
项目Demo:https://域名/fxhui/DatabaseManagement