65.9K
CodeProject 正在变化。 阅读更多。
Home

面向 .NET WPF 开发人员的最佳文本编辑器组件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2015年9月3日

CPOL

7分钟阅读

viewsIcon

25861

面向 .NET WPF 开发人员的最佳文本编辑器组件

AvalonEdit

可用解决方案概述……

对于那些创建用于分发和/或销售的桌面应用程序的软件专业人员来说,有时需要向用户呈现已编辑的文本,或者允许应用程序的用户像在众多现有 IDE 中输入源代码一样输入文本。

大多数情况下,这类应用程序的目标用户是其他技术专业人员,因此需要一个高质量的文本编辑器控件,这个控件可以根据应用程序的需求进行配置,而无需从头开发。

在这方面,需要将此类组件集成到其应用程序中的 .NET WPF 开发人员有多种选择。其中一个流行的开源组件是“ScintillaNET”,其最新版本可以在这里找到。

然而,“ScintillaNET”过去和现在主要都是为“Windows Forms”应用程序设计的,尽管它可以通过使用“Windows Form Host”控件托管在 WPF 中(参见此链接)。通过使用托管控件,如果被托管的控件与容器不完全兼容,可能会出现问题。而且由于 ScintillaNET 似乎经历了一些变动,这可能是一个值得关注的问题。尽管如此,在提供的链接中,所有必要的模块都可以下载,以便您可以进行充分的测试,以确保满意。

选择商业组件可能会提供任何应用程序所需的最有效和功能最丰富的选项,但这类产品似乎相当昂贵。“ActiPro Software”有一款看起来非常出色的产品(参见此链接),但其单个许可证的费用约为 399.00 美元。对于独立专业人士来说,如果他们不确定自己最终产品的市场表现如何,这样的开销可能会令人望而却步。

Black Falcon Software 已经有一款产品上市,另一款产品正在完成开发,即将发布。这两款产品都需要一个文本编辑器,以便向各自的用户呈现 SQL、VB.NET 和 C# 代码。

在 Black Falcon Software 的旗舰产品“SQL Server Source Control for Developers”中,标准的 WPF RichTextbox 控件被用于此目的,效果尚可,但并不如期望的那样理想,因为 RichTextbox 组件更适合类似文字处理的功能,而不是操作基于文本的源代码。

在尝试于第二款产品中使用 RichTextbox 来显示 VB.NET 或 C# 代码时,很明显这种用法对用户来说是完全不可接受的。

毫不奇怪,即使使用了“Courier New”字体,关于如何配置此控件以适当处理源代码的文档也寥寥无几。因此,我们开始寻找一种经济实惠的替代方案。

解决方案 – SharpDevelop 的 “AvalonEdit”

同样,除了上面提到的两种替代方案,能满足这种需求的可用选项并不多。然而,有一个选项似乎相当稳定,可以作为开源产品免费获得,并且来自一个相对成熟的产品团队,即“SharpDevelop”团队,他们至今仍在积极进行开发。

隆重介绍 “AvalonEdit”,它是著名的 .NET 开发 IDE “SharpDevelop” 的基础。

作为一个文本编辑器,“AvalonEdit” 是一个相当庞大的项目。由于它本身就支持一个功能齐全的 .NET IDE,因此它几乎具备了支持任何需要此功能的 WPF 桌面应用程序所必需的所有能力。

由于“AvalonEdit”作为一个独立的包提供,因此在互联网上的许多地方都能找到它。采用这些分发版本的问题在于,你永远无法确定是否能获得最新版本,而从“SharpDevelop”团队自己提供的包则可以保证。因此,最好的途径是访问“SharpDevelop”的网站,下载符合您要求的整个 IDE 包,其中既包含“AvalonEdit”项目,也包含一个相应的示例项目,让您可以快速对该编辑器进行测试。

当您通过上述链接访问该网站时,您将进入主页。选择第一个选项,它将带您进入“SharpDevelop” IDE 页面。到达那里后,在主菜单中选择“Download”选项。

进入“Download”页面后,您会看到有很多下载选项。最新版本的“SharpDevelop” IDE (5.0) 目前仅支持 C# 语言。这是否会影响相应版本的“AvalonEdit”所支持的语言,我们尚不确定。但必须假设“AvalonEdit”仍将支持其原有的语言集,其中也包括 VB.NET,因为“AvalonEdit”是其自身的一个子项目。

尽管如此,对此有顾虑的开发人员可以向网站人员发送电子邮件咨询,或者干脆下载支持 VB.NET 和 C# 的 4.4 版本 IDE。Black Falcon Software 选择了 4.4 版本,并简单地为其产品分发所使用的框架重新编译了源代码。

从 Zip 文件中解压出所有源代码后,您可以从后续的目录结构中提取出单个的“AvalonEdit”项目,如下所示……

AvalonEditDirectoryStructure

要获取相应的示例项目,请进入“samples”子目录并提取“AvalonEdit.Sample”项目,如下所示……

AvalonEditSampleDirectoryStructure

因为这两个项目是自包含的,您可以轻松地将它们放入自己的 Visual Studio 解决方案中,并针对您的应用程序开发目标框架进行重新编译。

开箱即用,“AvalonEdit”通过使用扩展名为“xshd”的语言语法支持 XML 文件来支持以下开发语言(所有这些文件都包含在源代码下载中;通过开发自定义语法文件可以支持新的语言)。

  • ASP/XHTML
  • Boo
  • Coco
  • CSS
  • C++
  • C#
  • HTML
  • Java
  • JavaScript
  • Patch
  • PHP
  • PowerShell
  • TeX
  • VBNET
  • XML
  • XmlDoc

使用“AvalonEdit”

实现“AvalonEdit”相当直接。您所要做的就是在您的项目中添加对新编译的程序集 ICSharpCode.AvalonEdit.dll 的引用,然后就可以开始了。

在您的 XAML 标记中

接下来,在将要托管“AvalonEdit”的窗口或页面的 XAML 头部代码中添加以下命名空间指令……

xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"

最后,将以下 XAML 标记放置在您的 WPF 窗口或页面中(所示属性是可选的),然后您就可以开始在自己的应用程序中测试编辑器的功能了。

<avalonEdit:TextEditor Name="aeteSourceCode" 
FontFamily="Consolas" FontSize="10pt" 
SyntaxHighlighting="VBNET" HorizontalAlignment="Center" 
HorizontalScrollBarVisibility="Visible" 
VerticalScrollBarVisibility="Visible" IsReadOnly="True" 
Text="" Height="521" Width="1108">
</avalonEdit:TextEditor>

在上面的 XAML 标记中,请注意以下属性

  • SyntaxHighlighting=”VBNET”

    除非您只打算在“AvalonEdit”中使用单一语言,否则不必在 XAML 中设置此属性。在这种情况下,假定始终使用 VB.NET。此属性也可以通过编程方式设置。

  • HoriziontalScrollBarVisibility & VerticalScrollBarVisibility

    将这些属性设置为“Visible”将确保在出现溢出时,编辑器的滚动条始终可用。

  • IsReadOnly=”False”

    默认值为“False”。但是,如果您只想将编辑器用于显示目的,则将此属性设置为“True”。

在您的 XAML 后台代码模块中

在您的 XAML 后台代码模块的顶部,添加以下“Imports”(VB.NET) 或“using”(C#) 语句

Imports ICSharpCode.AvalonEdit (or) using ICSharpCode.AvalonEdit;

如果您不将以下语句添加到您的后台模块中,那么在声明各种“AvalonEdit”类时,您将必须使用完整的命名空间。

在某些情况下,您需要根据用户的选择来更改语法高亮,这时您将需要通过编程方式加载语法文件。这可以通过以下示例代码完成……

VB.NET

Private Sub Set_AvalonEditTextEditorSyntaxHighlighting(ByVal psSyntaxHighlightingCode As String)

	Dim lsSourceCodeSyntaxHighlightingName  As String = ""

	Dim loXshdStream                        As Stream
	Dim loXmlTextReader                     As XmlTextReader   

	lsSourceCodeSyntaxHighlightingName = _
	IIf(psSyntaxHighlightingCode.Trim().Equals("CS"), "C#", "VBNET")

	' ---
	' load editor syntax highlighting file
	' ---
	loXshdStream = Nothing

	Select Case lsSourceCodeSyntaxHighlightingName
		Case "C#":
			loXshdStream = File.OpenRead(Convert.ToString("CSharp-Mode.xshd"))

		Case "VBNET":
			loXshdStream = File.OpenRead(Convert.ToString("VBNET-Mode.xshd"))
	End Select

	loXmlTextReader = New XmlTextReader(loXshdStream)
	aeteSourceCode.SyntaxHighlighting = _
	ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader.Load_
	(loXmlTextReader, ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance)

	' ---
	' set editor indentation settings
	' ---
	Select Case lsSourceCodeSyntaxHighlightingName
		Case "XML"
			aeteSourceCode.TextArea.IndentationStrategy = _
			New ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy()
			Exit Select
		Case "C#", "C++", "PHP", "Java"
			aeteSourceCode.TextArea.IndentationStrategy = _
			New ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy_
                        (aeteSourceCode.Options)
			Exit Select
		Case Else
			aeteSourceCode.TextArea.IndentationStrategy = _
			New ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy()
			Exit Select
	End Select
End Sub

C#

private void Set_AvalonEditTextEditorSyntaxHighlighting(string psSyntaxHighlightingCode)
{
	string         lsSourceCodeSyntaxHighlightingName = "";

	Stream         loXshdStream = default(Stream);
	XmlTextReader  loXmlTextReader = default(XmlTextReader);

	lsSourceCodeSyntaxHighlightingName = 
	(psSyntaxHighlightingCode.Trim().Equals("CS") ? "C#" : "VBNET");

	// ---
	// load editor syntax highlighting file
	// ---
	loXshdStream = null;

	switch (lsSourceCodeSyntaxHighlightingName) {
		case "C#":
			loXshdStream = File.OpenRead(Convert.ToString("CSharp-Mode.xshd"));

			break;
		case "VBNET":
			loXshdStream = File.OpenRead(Convert.ToString("VBNET-Mode.xshd"));
			break;
	}

	loXmlTextReader = new XmlTextReader(loXshdStream);
	aeteSourceCode.SyntaxHighlighting = _
              ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader.Load
	(loXmlTextReader, ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance);

	// ---
	// set editor indentation settings
	// ---
	switch (lsSourceCodeSyntaxHighlightingName) {
		case "XML":
			aeteSourceCode.TextArea.IndentationStrategy = 
			new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
			break;
		case "C#":
		case "C++":
		case "PHP":
		case "Java":
			aeteSourceCode.TextArea.IndentationStrategy = 
			new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy_
			(aeteSourceCode.Options);
			break;		
		default:
			aeteSourceCode.TextArea.IndentationStrategy = 
			new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
			break;
	}
}

到目前为止所提供的信息并未涵盖“AvalonEdit”的复杂实现,因为这个工具的功能相当广泛。然而,这些信息应该足以让您入门,以便您可以试验您确实想要包含的功能。

一篇由“AvalonEdit”的作者 Daniel Grunwald 撰写的优秀文章,描述了“AvalonEdit”更深入的细节,可以在“The Code Project”网站的这里找到。

© . All rights reserved.