?如何實現 WPF 代碼查看器控件
CodeViewer
作者:WPFDevelopersOrg - 驚鏵
原文鏈接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers
框架使用
.NET40
;Visual Studio 2019
;代碼展示需要使用到
AvalonEdit
是基于WPF
的代碼顯示控件,項目地址[2],支持C#
,javascript
,C++
,XML
,HTML
,Java
等語言的關鍵字高亮顯示。AvalonEdit
也是支持自定義的高亮配置,對于需要編寫腳本編輯器的場景非常適用。可通過配置
CustomHighlighting.xshd
文件,可以對高亮顯示做自定義設置。以下能夠實現
ifelse
高亮格式設置,代碼如下:
<?xml?version="1.0"?>
<SyntaxDefinition?name="Custom?Highlighting"?xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"><RuleSet><Keywords?fontWeight="bold"?foreground="Blue"><Word>if</Word><Word>else</Word></Keywords></RuleSet>
</SyntaxDefinition>
1)新建 SourceCodeModel.cs
用作記錄代碼源碼地址源碼類型等。
namespace?WPFDevelopers.Samples.Controls
{public?class?SourceCodeModel{public?CodeType?CodeType?{?get;?set;?}public?string?Haader?{?get;?set;?}public?string?CodeSource?{?get;?set;?}}public?enum?CodeType{Xaml,CSharp,}
}
2)新建 CodeViewer.xaml
代碼如下:
<ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"><Style?TargetType="{x:Type?controls:CodeViewer}"><Setter?Property="FontSize"?Value="{StaticResource?NormalFontSize}"/><Setter?Property="Template"><Setter.Value><ControlTemplate?TargetType="{x:Type?controls:CodeViewer}"><TabControl?x:Name="PART_TabControl"><TabControl.Resources><Style?TargetType="TabPanel"><Setter?Property="HorizontalAlignment"?Value="Right"/></Style></TabControl.Resources><TabItem?x:Name="PART_TabItemContent"?Header="Sample"?Content="{TemplateBinding?Content}"/></TabControl><ControlTemplate.Triggers><Trigger?Property="Content"?Value="{x:Null}"><Setter?Property="Visibility"?TargetName="PART_TabItemContent"?Value="Collapsed"/><Setter?Property="SelectedIndex"?TargetName="PART_TabControl"?Value="1"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>
3)新建 CodeViewer.cs
繼承ContentControl
代碼如下:
Content
用來展示控件。增加公共集合屬性用做存放代碼信息
SourceCodes
,重寫控件時循環SourceCodes
增加TabItem
到PART_TabControl
中。
using?ICSharpCode.AvalonEdit;
using?ICSharpCode.AvalonEdit.Editing;
using?ICSharpCode.AvalonEdit.Highlighting;
using?System;
using?System.Collections.ObjectModel;
using?System.IO;
using?System.Windows;
using?System.Windows.Controls;
using?static?System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;namespace?WPFDevelopers.Samples.Controls
{[TemplatePart(Name?=?TabControlTemplateName,?Type?=?typeof(TabControl))]public?class?CodeViewer?:?ContentControl{private?static?readonly?Type?_typeofSelf?=?typeof(CodeViewer);public?ObservableCollection<SourceCodeModel>?SourceCodes?{?get;?}?=?new?ObservableCollection<SourceCodeModel>();private?const?string?TabControlTemplateName?=?"PART_TabControl";private?TabControl?_tabControl?=?null;static?CodeViewer(){DefaultStyleKeyProperty.OverrideMetadata(_typeofSelf,new?FrameworkPropertyMetadata(_typeofSelf));}public?override?void?OnApplyTemplate(){base.OnApplyTemplate();_tabControl?=?GetTemplateChild(TabControlTemplateName)?as?TabControl;foreach?(var?item?in?SourceCodes){var?tabItem?=?CreateTabItem(item);_tabControl.Items.Add(tabItem);}}TabItem?CreateTabItem(SourceCodeModel?codeModel){if(codeModel==?null)return?null;var?partTextEditor?=?new?TextEditor();partTextEditor.Options?=?new?TextEditorOptions?{?ConvertTabsToSpaces?=?true?};partTextEditor.TextArea.SelectionCornerRadius?=?0;partTextEditor.SetResourceReference(TextArea.SelectionBrushProperty,?"WindowBorderBrushSolidColorBrush");partTextEditor.TextArea.SelectionBorder?=?null;partTextEditor.TextArea.SelectionForeground?=?null;partTextEditor.IsReadOnly?=?false;partTextEditor.ShowLineNumbers?=?true;partTextEditor.FontFamily?=?DrawingContextHelper.FontFamily;partTextEditor.Text?=?GetCodeText(codeModel.CodeSource);var?tabItem?=?new?TabItem{Content?=?partTextEditor};switch?(codeModel.CodeType){case?CodeType.Xaml:partTextEditor.SyntaxHighlighting?=?HighlightingManager.Instance.GetDefinitionByExtension(".XML");tabItem.Header?=?codeModel.Haader?==?null???"Xaml"?:?codeModel.Haader;break;case?CodeType.CSharp:partTextEditor.SyntaxHighlighting?=?HighlightingManager.Instance.GetDefinitionByExtension(".CS");tabItem.Header?=?codeModel.Haader?==?null???"CSharp"?:?codeModel.Haader;break;}return?tabItem;}string?GetCodeText(string?codeSource){var?code?=?string.Empty;var?uri?=?new?Uri(codeSource,?UriKind.Relative);var?resourceStream?=?Application.GetResourceStream(uri);if?(resourceStream?!=?null){var?streamReader?=?new?StreamReader(resourceStream.Stream);code?=?streamReader.ReadToEnd();return?code;}return?code;}}
}
4)新建 WPFDevelopers.SamplesCode.csproj
項目,在VS
右鍵項目添加現有項目
將所需要讀取的代碼文件添加為鏈接
就能得到以下地址:
<Resource?Include="..\WPFDevelopers.Samples\ExampleViews\AnimationNavigationBar3DExample.xaml"><Link>ExampleViews\AnimationNavigationBar3DExample.xaml</Link>
</Resource>
4)修改Example
代碼如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.AnimationNavigationBar3DExample"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"?xmlns:d="http://schemas.microsoft.com/expression/blend/2008"?xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"mc:Ignorable="d"?d:DesignHeight="450"?d:DesignWidth="800"><controls:CodeViewer><!--此處放展示控件--><controls:CodeViewer.SourceCodes><controls:SourceCodeModel?CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/AnimationNavigationBar3DExample.xaml"?CodeType="Xaml"/><controls:SourceCodeModel?CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/AnimationNavigationBar3DExample.xaml.cs"?CodeType="CSharp"/></controls:CodeViewer.SourceCodes></controls:CodeViewer>
</UserControl>

參考資料
[1]
原文鏈接: https://github.com/WPFDevelopersOrg/WPFDevelopers
[2]地址: https://github.com/icsharpcode/AvalonEdit