基于WPF实现代码查看器控件
驚鏵 人气:0如何实现 WPF 代码查看器控件
框架使用.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>
5)修改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>
效果图
加载全部内容