时间:2022年02月14日 | 作者 : aaronyang | 分类 : WPF | 浏览: 712次 | 评论 0 人
验证xml,把当前的xml内容用XmlDocument. Load 加载文本,报的异常来验证xml
https://github.com/ay2015/avaedit/
效果图
下面2个接口,对文字背景修改,一个应该是线
IBackgroundRenderer, IVisualLineTransformer
定义一个外观的文本块,继承TextSegment
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 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 class TextMarkerService : IBackgroundRenderer, IVisualLineTransformer { private readonly TextEditor textEditor; private readonly TextSegmentCollection<TextMarker> markers; 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 == 0) { 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 = 3 }; 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), 1); usedPen.Freeze(); const double offset = 2.5; int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4); 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 = 0; i < count; i++) { yield return new Point(start.X + (i * offset), start.Y - ((i + 1) % 2 == 0 ? offset : 0)); } } 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); } }
新建一个用户控件AvaEditor.xaml
前台代码
<UserControl x:Class="avaedit.AvaEditor" 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:local="clr-namespace:avaedit" mc:Ignorable="d" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.CommandBindings> <CommandBinding Command="local:AvaEditor.ValidateCommand" Executed="Validate"/> </UserControl.CommandBindings> <Grid> <avalonEdit:TextEditor x:Name="textEditor" SyntaxHighlighting="XML" ShowLineNumbers="True" > <avalonEdit:TextEditor.ContextMenu> <ContextMenu> <MenuItem Command="Undo" /> <MenuItem Command="Redo" /> <Separator/> <MenuItem Command="Cut" /> <MenuItem Command="Copy" /> <MenuItem Command="Paste" /> <Separator/> <MenuItem Command="local:AvaEditor.ValidateCommand" /> </ContextMenu> </avalonEdit:TextEditor.ContextMenu> </avalonEdit:TextEditor> </Grid> </UserControl>
后台代码:
public partial class AvaEditor : UserControl { private static readonly ICommand validateCommand = new RoutedUICommand("验证XML", "Validate", typeof(AvaEditor), new InputGestureCollection { new KeyGesture(Key.V, ModifierKeys.Control | ModifierKeys.Shift) }); public static ICommand ValidateCommand { get { return validateCommand; } } public AvaEditor() { InitializeComponent(); Loaded += AvaEditor_Loaded; } private ToolTip toolTip; private TextMarkerService textMarkerService; private void AvaEditor_Loaded(object sender, RoutedEventArgs e) { Loaded -= AvaEditor_Loaded; textMarkerService = new TextMarkerService(textEditor); var 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); 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 >= 1 && 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 < 0) { endOffset = textEditor.Document.TextLength; } int length = endOffset - offset; if (length < 2) { length = Math.Min(2, textEditor.Document.TextLength - offset); } textMarkerService.Create(offset, length, message); } } }
然后找一个页面使用下就行了
<local:AvaEditor Grid.Row="1"/>
加个背景色
public void Create(int offset, int length, string message) { var m = new TextMarker(offset, length); markers.Add(m); m.MarkerColor = Colors.Red; m.BackgroundColor = Colors.Yellow; m.ToolTip = message; Redraw(m); }
官方示例
<SyntaxDefinition name="Custom Highlighting" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> <Color name="Comment" foreground="#FF00FF" /> <Color name="String" foreground="Blue" /> <!-- This is the main ruleset. --> <RuleSet> <Span color="Comment" begin="//" /> <Span color="Comment" multiline="true" begin="/\*" end="\*/" /> <Span color="String"> <Begin>"</Begin> <End>"</End> <RuleSet> <!-- nested span for escape sequences --> <Span begin="\\" end="." /> </RuleSet> </Span> <Keywords fontWeight="bold" foreground="Blue"> <Word>if</Word> <Word>else</Word> <!-- ... --> </Keywords> <Keywords fontWeight="bold" fontStyle="italic" foreground="Red"> <Word>AvalonEdit</Word> </Keywords> <!-- Digits --> <Rule foreground="DarkBlue"> \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> </RuleSet> </SyntaxDefinition>
给颜色取名字,下方定义规则
下面定义个lua的高亮规则
新建个txt,改名字lua.xshd 文件类型改为 嵌入的资源,你也可以是资源,主要嵌入到程序还能读取xml内容
<?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"> [?,.;()\[\]{}+\-/%*<>^+~!|&]+ </Rule> </RuleSet> </SyntaxDefinition>
然后在后台找个loaded的地方指定SyntaxHighlighting属性
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); } }
运行后,粘贴lua代码
-- 以只读方式打开文件 file = io.open("test.lua", "r") -- 设置默认输入文件为 test.lua io.input(file) -- 输出文件第一行 print(io.read()) -- 关闭打开的文件 io.close(file) -- 以附加的方式打开只写文件 file = io.open("test.lua", "a") -- 设置默认输出文件为 test.lua io.output(file) -- 在文件最后一行添加 Lua 注释 io.write("-- test.lua 文件末尾注释") -- 关闭打开的文件 io.close(file)
你也可以设置文件为资源
using (XmlTextReader xmlTextReader = new XmlTextReader(Application.GetResourceStream(new Uri("pack://application:,,,/avaedit;component/lua.xshd")).Stream))
{
textEditor.SyntaxHighlighting = HighlightingLoader.Load(xmlTextReader, HighlightingManager.Instance);
}
加载文件textEditor.Load(filename);
官方写法,可以给个名字,注册文件后缀和 高亮规则,那么就可以直接指定这个名字了,而不是传递一些 高亮规则的xml
IHighlightingDefinition customHighlighting; using (Stream s = typeof(Window1).Assembly.GetManifestResourceStream("AvalonEdit.Sample.CustomHighlighting.xshd")) { if (s == null) throw new InvalidOperationException("Could not find embedded resource"); using (XmlReader reader = new XmlTextReader(s)) { customHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd. HighlightingLoader.Load(reader, HighlightingManager.Instance); } } // and register it in the HighlightingManager HighlightingManager.Instance.RegisterHighlighting("Custom Highlighting", new string[] { ".cool" }, customHighlighting);
SearchPanel.Install(textEditor.TextArea);
运行后按 Ctrl+F ,面板有点丑,自己可以修改源码改外观
=============2022 02 16 ============================== www.ayjs.net==================================
推荐您阅读更多有关于“avalonedit,wpf,”的文章
抖音:wpfui 工作wpf
目前在合肥企迈科技公司上班,加我QQ私聊
2023年11月网站停运,将搬到CSDN上
AYUI8全源码 Github地址:前往获取
杨洋(AaronYang简称AY,安徽六安人)和AY交流
高中学历,2010年开始web开发,2015年1月17日开始学习WPF
声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费
查看捐赠AYUI7.X MVC教程 更新如下:
第一课 第二课 程序加密教程
额 本文暂时没人评论 来添加一个吧
发表评论