zoukankan      html  css  js  c++  java
  • AvalonEdit验证语法并提示错误

    <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 >= 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);
            }
        }
    }
    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 == 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);
        }
    }
  • 相关阅读:
    cookie小结
    WEB服务器,TOMCAT和servlet之间的关系
    HTTP协议基础总结
    servlet总结
    注解总结
    常使用的String方法
    变量&&常量
    标识符&&注释&&关键字
    配置环境变量&&OpenJDK和OracleJDK区别
    逆向工程__Generate插件安装 && xml配置文件解析 &&使用反向生成代码 && 接口说明
  • 原文地址:https://www.cnblogs.com/foreachlife/p/avaloneditValidation.html
Copyright © 2011-2022 走看看