基于WPF实现代码查看器控件

 更新时间:2022年11月23日 09:39:40   作者:驚鏵  
这篇文章主要为大家详细介绍了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增加TabItemPART_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>

效果图

到此这篇关于基于WPF实现代码查看器控件的文章就介绍到这了,更多相关WPF代码查看器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# Memcached缓存用法实例详解

    C# Memcached缓存用法实例详解

    这篇文章主要介绍了C#中Memcached缓存用法,以实例形式详细讲述了在C#中针对Memcached缓存的各种操作,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • C#随机生成Unicode类型字符串

    C#随机生成Unicode类型字符串

    做测试时经常需要生成一些随机数据,最常见的就是生成随机字符串。而且往往要生成Unicode字符串,有时还要特别指定生成的字符的语言范围。下面是我觉得比较灵活的方法:
    2013-04-04
  • unity 如何修改材质属性和更换shader

    unity 如何修改材质属性和更换shader

    这篇文章主要介绍了unity 修改材质属性和更换shader的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Qt之调用C#的动态库的解决方法

    Qt之调用C#的动态库的解决方法

    这篇文章给大家介绍了Qt之调用C#的动态库的解决方法,环境使用的是VS2019+Qt5.12,感兴趣的朋友一起看看吧
    2021-10-10
  • 如何在C#中使用Dapper ORM

    如何在C#中使用Dapper ORM

    这篇文章主要介绍了如何在C#中使用Dapper ORM,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • C# DialogResult用法案例详解

    C# DialogResult用法案例详解

    这篇文章主要介绍了C# DialogResult用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C#线程同步的几种方法总结

    C#线程同步的几种方法总结

    在本篇文章里小编给大家整理的是关于C#线程同步的几种方法总结,需要的朋友们可以学习下。
    2020-02-02
  • C#关机小程序源码

    C#关机小程序源码

    这是用所学习的C#做的一个关机小程序,功能不多,只是为了练手,需要的朋友可以参考下
    2012-10-10
  • c# 获取数据库中所有表名称的方法

    c# 获取数据库中所有表名称的方法

    在很多情况下我们需要将指定的数据库中的所有表都列出来。在使用c#进行软件开发时,我们有哪些方法可是实现这个目的呢?本人对此进行概要的总结,有以下6中方式可以实现这个目的。
    2010-02-02
  • Unity中 ShaderGraph 实现超级炫酷的溶解效果入门级教程

    Unity中 ShaderGraph 实现超级炫酷的溶解效果入门级教程

    这篇文章主要介绍了Unity中的 ShaderGraph 实现超级炫酷的溶解效果入门级教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07

最新评论