WPF 使用AvalonEdit实现代码编译器

WPF 使用AvalonEdit实现代码编译器

1.先在项目中NuGet安装一下AvalonEdit,如下图,选择第一项:
在这里插入图片描述
2.接着把下面的文件内容,保存为Lua.xshd文件名的文件(这个文件主要设置关键字显示的样式):

<?xml version="1.0"?>
<SyntaxDefinition name="SharpLua" extensions=".slua;.lua" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
  <!-- The named colors 'Comment' and 'String' are used in SharpDevelop to detect if a line is inside a multiline string/comment -->
  <Color name="Comment" foreground="#ff999999" exampleText="-- comment" />
  <Color name="String" foreground="#fff99157" />
  <Color name="Punctuation" />
  <Color name="MethodCall" foreground="#ffffcc66" fontWeight="bold"/>
  <Color name="NumberLiteral" foreground="#ff99cc99"/>
  <Color name="NilKeyword" fontWeight="bold"/>
  <Color name="Keywords" fontWeight="bold" foreground="#ff6699cc" />
  <Color name="GotoKeywords" foreground="#ffcc99cc" />
  <Color name="Visibility" fontWeight="bold" foreground="#fff99157"/>
  <Color name="TrueFalse" fontWeight="bold" foreground="#ff66cccc" />

  <RuleSet name="CommentMarkerSet">
    <Keywords fontWeight="bold" foreground="#fff2777a">
      <Word>TODO</Word>
      <Word>FIXME</Word>
    </Keywords>
    <Keywords fontWeight="bold" foreground="#fff2777a">
      <Word>HACK</Word>
      <Word>UNDONE</Word>
    </Keywords>
  </RuleSet>

  <!-- This is the main ruleset. -->
  <RuleSet>

    <Span color="Comment">
      <Begin color="XmlDoc/DocComment">---</Begin>
      <RuleSet>
        <Import ruleSet="XmlDoc/DocCommentSet"/>
        <Import ruleSet="CommentMarkerSet"/>
      </RuleSet>
    </Span>


    <Span color="Comment" ruleSet="CommentMarkerSet" multiline="true">
      <Begin>--\[[=]*\[</Begin>
      <End>\][=]*]</End>
    </Span>


    <Span color="Comment" ruleSet="CommentMarkerSet">
      <Begin>--</Begin>
    </Span>

    <Span color="String">
      <Begin>"</Begin>
      <End>"</End>
      <RuleSet>
        <!-- span for escape sequences -->
        <Span begin="\\" end="."/>
      </RuleSet>
    </Span>

    <Span color="String">
      <Begin>'</Begin>
      <End>'</End>
      <RuleSet>
        <!-- span for escape sequences -->
        <Span begin="\\" end="."/>
      </RuleSet>
    </Span>

    <Span color="String" multiline="true">
      <Begin color="String">\[[=]*\[</Begin>
      <End>\][=]*]</End>
    </Span>

    <Keywords color="TrueFalse">
      <Word>true</Word>
      <Word>false</Word>
    </Keywords>

    <Keywords color="Keywords">
      <Word>and</Word>
      <Word>break</Word>
      <Word>do</Word>
      <Word>else</Word>
      <Word>elseif</Word>
      <Word>end</Word>
      <Word>false</Word>
      <Word>for</Word>
      <Word>function</Word>
      <Word>if</Word>
      <Word>in</Word>
      <Word>local</Word>
      <!--<Word>nil</Word>-->
      <Word>not</Word>
      <Word>or</Word>
      <Word>repeat</Word>
      <Word>return</Word>
      <Word>then</Word>
      <Word>true</Word>
      <Word>until</Word>
      <Word>while</Word>
      <Word>using</Word>
      <Word>continue</Word>
    </Keywords>

    <Keywords color="GotoKeywords">
      <Word>break</Word>
      <Word>return</Word>
    </Keywords>

    <Keywords color="Visibility">
      <Word>local</Word>
    </Keywords>

    <Keywords color="NilKeyword">
      <Word>nil</Word>
    </Keywords>

    <!-- Mark previous rule-->
    <Rule color="MethodCall">
      \b
      [\d\w_]+  # an identifier
      (?=\s*\() # followed by (
    </Rule>
    <Rule color="MethodCall">
      \b
      [\d\w_]+  # an identifier
      (?=\s*\") # followed by "
    </Rule>
    <Rule color="MethodCall">
      \b
      [\d\w_]+  # an identifier
      (?=\s*\') # followed by '
    </Rule>
    <Rule color="MethodCall">
      \b
      [\d\w_]+  # an identifier
      (?=\s*\{) # followed by {
    </Rule>
    <Rule color="MethodCall">
      \b
      [\d\w_]+  # an identifier
      (?=\s*\[) # followed by [
    </Rule>

    <!-- Digits -->
    <Rule color="NumberLiteral">
      \b0[xX][0-9a-fA-F]+  # hex number
      |
      ( \b\d+(\.[0-9]+)?   #number with optional floating point
      | \.[0-9]+           #or just starting with floating point
      )
      ([eE][+-]?[0-9]+)? # optional exponent
    </Rule>

    <Rule color="Punctuation">
      [?,.;()\[\]{}+\-/%*&lt;&gt;^+~!|&amp;]+
    </Rule>
  </RuleSet>
</SyntaxDefinition>

把Lua.xshd放到解决方案资源管理器中,生成操作改为嵌入的资源
在这里插入图片描述
3.xaml里的代码如下:

<avalonEdit:TextEditor
 Grid.Row="2"
 xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
 Name="textEditor"
 FontFamily="Consolas"
 FontSize="10pt"
 ShowLineNumbers="True"
 LostFocus="TextEditor_LostFocus"/>

然后在窗体的loaded事件中运行下面的代码即可:

//快速搜索功能
SearchPanel.Install(textEditor.TextArea);
//设置语法规则
string name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Lua.xshd";
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
using (System.IO.Stream s = assembly.GetManifestResourceStream(name))
{
    using (XmlTextReader reader = new XmlTextReader(s))
    {
        var xshd = HighlightingLoader.LoadXshd(reader);
        textEditor.SyntaxHighlighting = HighlightingLoader.Load(xshd, HighlightingManager.Instance);
    }
}

如果需要加载需要的代码文件:

textEditor.Load(filename);

效果:
在这里插入图片描述
添加右键菜单(在窗体构造函数中添加如下即可):

ContextMenu aMenu = new ContextMenu();
MenuItem copyMenuItem = new MenuItem();
copyMenuItem.Header = "复制(C)";
copyMenuItem.Click += (sender, eventArgs) => rtb_TextArea.Copy();
aMenu.Items.Add(copyMenuItem);
MenuItem selectAllItem = new MenuItem();
selectAllItem.Header = "全选(A)";
selectAllItem.Click += (sender, eventArgs) => rtb_TextArea.SelectAll();
aMenu.Items.Add(selectAllItem);
rtb_TextArea.ContextMenu = aMenu;

扩展介绍:
或者我们也可以将语法显示的xshd配置文件的文件属性设置为不复制,生成操作设置为Resource;
然后使用绝对路径调用:

using (XmlTextReader xmlTextReader = new XmlTextReader(Application.GetResourceStream(new Uri("pack://application:,,,/WPF001;component/Files/Config.xshd")).Stream))
{
     rtb_ContentArea.SyntaxHighlighting = HighlightingLoader.Load(xmlTextReader, HighlightingManager.Instance);
}

其他参考:
通过Nuget安装AvalonEdit,并在页面添加控件

 <avalonEdit:TextEditor
                        xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
                        Name="TextEditor"
                        SyntaxHighlighting="C#"
                        FontFamily="Consolas"
                        FontSize="14"
                        WordWrap ="True"
                        LineNumbersForeground="#FF2B91AF"
                        ShowLineNumbers="True">
     <avalonEdit:TextEditor.Options>
         <avalonEdit:TextEditorOptions ShowSpaces="True" WordWrapIndentation="4" InheritWordWrapIndentation="true">
             <avalonEdit:TextEditorOptions.ColumnRulerPosition>
                 <system:Int32>10</system:Int32>
             </avalonEdit:TextEditorOptions.ColumnRulerPosition>
         </avalonEdit:TextEditorOptions>
     </avalonEdit:TextEditor.Options>
</avalonEdit:TextEditor>

参数含义
xmlns:avalonEdit:命名空间,也可以直接写在调用该控件的窗体内
SyntaxHighlighting:设置高亮
ShowLineNumbers:是否显示行号
LineNumbersForeground:设置编辑器行号颜色
ShowSpaces:是否显示空格
WordWrapIndentation:换行缩进距离
InheritWordWrapIndentation:是否继承上一行的换行缩进

备注:详细介绍
http://avalonedit.net/

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的基于 WPF MVVM 框架的上位机示例代码实现了一个简单的计数器功能: MainWindow.xaml: ``` <Window x:Class="WPFMVVMExample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF MVVM Example" Height="200" Width="300"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBlock Text="{Binding Count}" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Button Content="Increase" Command="{Binding IncreaseCountCommand}" Grid.Row="1" HorizontalAlignment="Center"/> </Grid> </Window> ``` MainWindow.xaml.cs: ``` using System.Windows; namespace WPFMVVMExample { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MainViewModel(); } } } ``` MainViewModel.cs: ``` using System.ComponentModel; using System.Windows.Input; namespace WPFMVVMExample { public class MainViewModel : INotifyPropertyChanged { private int _count; public int Count { get { return _count; } set { _count = value; OnPropertyChanged("Count"); } } public ICommand IncreaseCountCommand { get; private set; } public MainViewModel() { Count = 0; IncreaseCountCommand = new RelayCommand(IncreaseCount); } private void IncreaseCount() { Count++; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } } ``` RelayCommand.cs: ``` using System; using System.Windows.Input; namespace WPFMVVMExample { public class RelayCommand : ICommand { private readonly Action _execute; private readonly Func<bool> _canExecute; public RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Func<bool> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(); } public void Execute(object parameter) { _execute(); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } } } ``` 这个示例代码实现了一个简单的计数器功能,通过按钮点击可以增加计数器的值。在 ViewModel 中定义了一个 Count 属性和 IncreaseCountCommand 命令,Count 属性绑定到 TextBlock 控件的 Text 属性上,IncreaseCountCommand 命令绑定到 Button 控件的 Command 属性上。使用了 RelayCommand 类实现了 ICommand 接口,处理按钮点击事件。在 MainWindow.xaml.cs 中设置了 DataContext 为 MainViewModel 的实例,实现了界面和 ViewModel 的绑定。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值