基于WPF实现代码查看器控件
作者:驚鏵 发布时间:2022-10-06 03:32:11
标签:WPF,代码,查看
如何实现 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>
效果图
来源:https://mp.weixin.qq.com/s/TfplUzVCrcwMyWe2aDcPAQ


猜你喜欢
- 提出问题下面所给代码编译时正常,但是执行时会出错,请指出程序在执行时能够执行到编号为(1)(2)(3)的代码行中的哪一行。using Sys
- 前言最近在做项目的时候,有个需求就是实现自动轮播式的ViewPager,最直观的例子就是知乎日报顶部的ViewPager,它内部有着好几个子
- 本文实例为大家分享了Android App获取屏幕旋转角度的具体代码,供大家参考,具体内容如下一、获取屏幕旋转角度的方法是:int rota
- 前面讲解了MediaPlayer播放网络音频,主要介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法,本文再来讲解一下Medi
- 前言众所周知,微信聊天中我们输入一些关键词会有表情雨下落,比如输入「生日快乐」「么么哒」会有相应的蛋糕、亲吻的表情雨下落,今天就来完成这个表
- Unity中的PostProcessBuild:深入解析与实用案例在Unity游戏开发中,我们经常需要在构建完成后对生成的应用程序进行一些额
- 本文实例为大家分享了android实现底部导航栏的具体代码,供大家参考,具体内容如下常见的底部导航栏动态效果实现步骤1.底部导航栏样式我们应
- 了解YMP框架YMP于2014年10月25日正式发布1.0版本,在此之前就已在实际项目中得到广泛使用,从最初仅限团队内部使用,到合作伙伴的开
- 简介对于一个APP来说,肯定会有一个AppBar,这个AppBar一般包含了APP的导航信息等。虽然我们可以用一个固定的组件来做为AppBa
- 具体代码如下所示:private string GetWeekName(DayOfWeek week) { &nb
- 本文实例讲述了Java面向对象程序设计:类的定义,静态变量,成员变量,构造函数,封装与私有,this概念与用法。分享给大家供大家参考,具体如
- 本文通过介绍了Asp.Net中MVC缓存的种类,以及他们之间的区别等内容,让学习者能够深入的了解MVC缓存的原理机制,以下是具体内容:缓存是
- 对流进行操作时要引用 using System.IO; 命名空间 FileStream常用的属性和方法:属性:CanRead 判断当前流是否
- 本文实例为大家分享了Flutter实现底部导航栏的具体代码,供大家参考,具体内容如下效果实现先将自动生成的main.dart里面的代码删除,
- 1、两个相关概念:Git和githubGit是一个开源的分布式 版本控制 系统,用以有效、高速的处理从很小到非常大的项目版本管理。 Git
- 面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。在面向对象程序设计(OOP)中,不必关心对象的具体实现。
- 一、需要自定义登录结果的场景在我之前的文章中,做过登录验证流程的源码解析。其中比较重要的就是当我们登录成功的时候,是由Authenticat
- 基于 kotlin/coroutine/retrofit/jetpack 打造,100来行代码,用法超级简单舒适设置默认Retrofit工厂
- 目录堆内存溢出原因:解决方案:栈内存溢出原因:解决方案:方法区和运行时常量池内存溢出原因:本机直接内存溢出原因:解决方案:元空间内存溢出原因
- 引言在Android应用中,列表有着举足轻重的地位,几乎所有的应用都有列表的身影,但是对于列表的交互体验一直是一个大问题。在性能比较好的设备