<UserControl x:Class="WpfTestApp.Xml.XmlEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:WpfTestApp="clr-namespace:WpfTestApp.Xml"> <UserControl.CommandBindings>
<CommandBinding Command="WpfTestApp:XmlEditor.ValidateCommand" Executed="Validate"/>
</UserControl.CommandBindings> <avalonedit:TextEditor Name="textEditor" FontFamily="Consolas" SyntaxHighlighting="XML" FontSize="8pt">
<avalonedit:TextEditor.Options>
<avalonedit:TextEditorOptions ShowSpaces="True" ShowTabs="True"/>
</avalonedit:TextEditor.Options>
<avalonedit:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Command="Undo" />
<MenuItem Command="Redo" />
<Separator/>
<MenuItem Command="Cut" />
<MenuItem Command="Copy" />
<MenuItem Command="Paste" />
<Separator/>
<MenuItem Command="WpfTestApp:XmlEditor.ValidateCommand" />
</ContextMenu>
</avalonedit:TextEditor.ContextMenu>
</avalonedit:TextEditor>
</UserControl>
public partial class XmlEditor : UserControl
{
private static readonly ICommand validateCommand = new RoutedUICommand("Validate XML", "Validate", typeof(MainWindow),
new InputGestureCollection { new KeyGesture(Key.V, ModifierKeys.Control | ModifierKeys.Shift) }); private readonly TextMarkerService textMarkerService;
private ToolTip toolTip; public static ICommand ValidateCommand
{
get { return validateCommand; }
} public XmlEditor()
{
InitializeComponent(); textMarkerService = new TextMarkerService(textEditor);
TextView textView = textEditor.TextArea.TextView;
textView.BackgroundRenderers.Add(textMarkerService);
textView.LineTransformers.Add(textMarkerService);
textView.Services.AddService(typeof(TextMarkerService), textMarkerService); textView.MouseHover += MouseHover;
textView.MouseHoverStopped += TextEditorMouseHoverStopped;
textView.VisualLinesChanged += VisualLinesChanged;
} private void MouseHover(object sender, MouseEventArgs e)
{
var pos = textEditor.TextArea.TextView.GetPositionFloor(e.GetPosition(textEditor.TextArea.TextView) + textEditor.TextArea.TextView.ScrollOffset);
bool inDocument = pos.HasValue;
if (inDocument)
{
TextLocation logicalPosition = pos.Value.Location;
int offset = textEditor.Document.GetOffset(logicalPosition); var markersAtOffset = textMarkerService.GetMarkersAtOffset(offset);
TextMarkerService.TextMarker markerWithToolTip = markersAtOffset.FirstOrDefault(marker => marker.ToolTip != null); if (markerWithToolTip != null)
{
if (toolTip == null)
{
toolTip = new ToolTip();
toolTip.Closed += ToolTipClosed;
toolTip.PlacementTarget = this;
toolTip.Content = new TextBlock
{
Text = markerWithToolTip.ToolTip,
TextWrapping = TextWrapping.Wrap
};
toolTip.IsOpen = true;
e.Handled = true;
}
}
}
} void ToolTipClosed(object sender, RoutedEventArgs e)
{
toolTip = null;
} void TextEditorMouseHoverStopped(object sender, MouseEventArgs e)
{
if (toolTip != null)
{
toolTip.IsOpen = false;
e.Handled = true;
}
} private void VisualLinesChanged(object sender, EventArgs e)
{
if (toolTip != null)
{
toolTip.IsOpen = false;
}
} private void Validate(object sender, ExecutedRoutedEventArgs e)
{
IServiceProvider sp = textEditor;
var markerService = (TextMarkerService)sp.GetService(typeof(TextMarkerService));
markerService.Clear(); try
{
var document = new XmlDocument { XmlResolver = null };
document.LoadXml(textEditor.Document.Text);
}
catch (XmlException ex)
{
DisplayValidationError(ex.Message, ex.LinePosition, ex.LineNumber);
}
} private void DisplayValidationError(string message, int linePosition, int lineNumber)
{
if (lineNumber >= && lineNumber <= textEditor.Document.LineCount)
{
int offset = textEditor.Document.GetOffset(new TextLocation(lineNumber, linePosition));
int endOffset = TextUtilities.GetNextCaretPosition(textEditor.Document, offset, System.Windows.Documents.LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol);
if (endOffset < )
{
endOffset = textEditor.Document.TextLength;
}
int length = endOffset - offset; if (length < )
{
length = Math.Min(, textEditor.Document.TextLength - offset);
} textMarkerService.Create(offset, length, message);
}
}
}
public class TextMarkerService : IBackgroundRenderer, IVisualLineTransformer
{
private readonly TextEditor textEditor;
private readonly TextSegmentCollection<TextMarker> markers; public sealed class TextMarker : TextSegment
{
public TextMarker(int startOffset, int length)
{
StartOffset = startOffset;
Length = length;
} public Color? BackgroundColor { get; set; }
public Color MarkerColor { get; set; }
public string ToolTip { get; set; }
} public TextMarkerService(TextEditor textEditor)
{
this.textEditor = textEditor;
markers = new TextSegmentCollection<TextMarker>(textEditor.Document);
} public void Draw(TextView textView, DrawingContext drawingContext)
{
if (markers == null || !textView.VisualLinesValid)
{
return;
}
var visualLines = textView.VisualLines;
if (visualLines.Count == )
{
return;
}
int viewStart = visualLines.First().FirstDocumentLine.Offset;
int viewEnd = visualLines.Last().LastDocumentLine.EndOffset;
foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart))
{
if (marker.BackgroundColor != null)
{
var geoBuilder = new BackgroundGeometryBuilder {AlignToWholePixels = true, CornerRadius = };
geoBuilder.AddSegment(textView, marker);
Geometry geometry = geoBuilder.CreateGeometry();
if (geometry != null)
{
Color color = marker.BackgroundColor.Value;
var brush = new SolidColorBrush(color);
brush.Freeze();
drawingContext.DrawGeometry(brush, null, geometry);
}
}
foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker))
{
Point startPoint = r.BottomLeft;
Point endPoint = r.BottomRight; var usedPen = new Pen(new SolidColorBrush(marker.MarkerColor), );
usedPen.Freeze();
const double offset = 2.5; int count = Math.Max((int) ((endPoint.X - startPoint.X)/offset) + , ); var geometry = new StreamGeometry(); using (StreamGeometryContext ctx = geometry.Open())
{
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
} geometry.Freeze(); drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
break;
}
}
} public KnownLayer Layer
{
get { return KnownLayer.Selection; }
} public void Transform(ITextRunConstructionContext context, IList<VisualLineElement> elements)
{} private IEnumerable<Point> CreatePoints(Point start, Point end, double offset, int count)
{
for (int i = ; i < count; i++)
{
yield return new Point(start.X + (i*offset), start.Y - ((i + )% == ? offset : ));
}
} public void Clear()
{
foreach (TextMarker m in markers)
{
Remove(m);
}
} private void Remove(TextMarker marker)
{
if (markers.Remove(marker))
{
Redraw(marker);
}
} private void Redraw(ISegment segment)
{
textEditor.TextArea.TextView.Redraw(segment);
} public void Create(int offset, int length, string message)
{
var m = new TextMarker(offset, length);
markers.Add(m);
m.MarkerColor = Colors.Red;
m.ToolTip = message;
Redraw(m);
} public IEnumerable<TextMarker> GetMarkersAtOffset(int offset)
{
return markers == null ? Enumerable.Empty<TextMarker>() : markers.FindSegmentsContaining(offset);
}
}

AvalonEdit验证语法并提示错误的更多相关文章

  1. 【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."

    API 管理 (APIM) 是一种为现有后端服务创建一致且现代化的 API 网关的方法. 问题描述 在设置了APIM客户端证书,用户保护后端API,让请求更安全. 但是,最近发现使用客户端证书的API ...

  2. 今天遇到一件开心事,在eclipse编写的代码在命令窗口中编译后无法运行,提示 “错误: 找不到或无法加载主类”

    java中带package和不带package的编译运行方式是不同的. 首先来了解一下package的概念:简单定义为,package是一个为了方便管理组织java文件的目录结构,并防止不同java文 ...

  3. jQuery validate运作流程以及重复提示错误问题

    一,运作流程 jQuery validate要想运作,首先要加载相应的js <script type="text/javascript" src="/js/clas ...

  4. asp.net mvc3 数据验证(二)——错误信息的自定义及其本地化

    原文:asp.net mvc3 数据验证(二)--错误信息的自定义及其本地化 一.自定义错误信息         在上一篇文章中所做的验证,在界面上提示的信息都是系统自带的,有些读起来比较生硬.比如: ...

  5. vue中npm run dev运行项目不能自动打开浏览器! 以及 webstorm跑vue项目jshint一直提示错误问题的解决方法!

    vue中npm run dev运行项目不能自动打开浏览器!以及 webstorm跑vue项目jshint一直提示错误问题的解决方法! 1.上个项目结束就很久没有使用vue了,最近打算用vue搭建自己的 ...

  6. Python3安装turtle提示错误:Command "python setup.py egg_info" failed with error code 1

    Python3安装turtle提示错误:Command "python setup.py egg_info" failed with error code 1 Python3.5安 ...

  7. Django-Form表单(验证、定制、错误信息、Select)

      Django form 流程 1.创建类,继承form.Form 2.页面根据类的对象自动创建html标签 3.提交,request.POST       封装到类的对象里,obj=UserInf ...

  8. MYSQL导入CSV格式文件数据执行提示错误(ERROR 1290): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement.

    MYSQL导入CSV格式文件数据执行提示错误(ERROR 1290): The MySQL server is running with the --secure-file-priv option s ...

  9. SVN“验证位置时发生错误”的解决办法

    验证位置时发生错误:“org.tigris.subversion.javahl.ClientException...... 验证位置时发生错误:“org.tigris.subversion.javah ...

随机推荐

  1. 如何避免HBase写入过快引起的各种问题

    首先我们简单回顾下整个写入流程 client api ==> RPC ==> server IPC ==> RPC queue ==> RPC handler ==> w ...

  2. 绛河 初识WCF4

    参考: http://blog.csdn.net/anlun/article/details/44860821 第四篇 初探通信--ChannelFactory 通过前几篇的学习,我们简单了解了WCF ...

  3. (1)Map集合 (2)异常机制 (3)File类 (4)I/O流

    1.Map集合(重点)1.1 常用的方法 Set<Map.Entry<K,V>> entrySet() - 用于将Map集合转换为Set集合. 其中Map.Entry<K ...

  4. 【2017-01-08】QTimer与QThread的调度时间精度

    在最近的项目开发中,我发现有的人喜欢用QThread来实现需要循环执行的工作流,而有的人又喜欢用QTimer来实现. 在表面上,两种实现方式似乎都可以,但我觉得QTimer的精度可能会有问题,首先看一 ...

  5. 【洛谷】【线段树】P1471 方差

    [题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...

  6. 【JavaScript】JavaScript(V8)实现输入输出

    首先看牛客网的样例:https://www.nowcoder.com/questionTerminal/dae9959d6df7466d9a1f6d70d6a11417 计算a+b的和,每行包行两个整 ...

  7. 禁止 "启动时恢复任何注册的应用程序"

    在关闭计算机时 有些程序会进行注册 并在下次启动时恢复关闭前的状态(Restart Manager) 比如Chrome浏览器 应用程序实现这一功能可以调用RegisterApplicationRest ...

  8. node-webkit,nwjs 系统托盘【Tray】实践

    参照自:https://www.cnblogs.com/xuanhun/p/3678943.html Tray包含title.tooltip.icon.menu.alticon五个属性. title属 ...

  9. 【转】如何在VMware上安装macOS Sierra 10.12

    本文主要介绍目前网络上比较流行的使用预安装镜像安装macOS 10.12的方法,并以9月20号发布的最新GM版本16A323为例. 安装方案 破解VMware 创建虚拟机,加载预安装镜像 初始化mac ...

  10. 《Python核心编程》第二版第五章答案

    本人python新手,答案自己做的,如果有问题,欢迎大家评论和讨论! 更新会在本随笔中直接更新. 5-1.整型.讲讲Python普通整型和长整型的区别. Python的标准整形类型是最通用的数字类型. ...