使用 AvalonEdit 自定义超链接

Chr*_*ris 3 c# wpf avalonedit

我正在尝试使用 AvalonEdit 创建自定义超链接。我创建了一个生成器(基于示例),它可以识别语法,并且可以设置 Uri:

  public class LinkGenerator : VisualLineElementGenerator
  {
    readonly static Regex imageRegex = new Regex(@"<mylink>", RegexOptions.IgnoreCase);

    public LinkGenerator()
    {}

    Match FindMatch(int startOffset)
    {
        // fetch the end offset of the VisualLine being generated
        int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
        TextDocument document = CurrentContext.Document;
        string relevantText = document.GetText(startOffset, endOffset - startOffset);
        return imageRegex.Match(relevantText);
    }

    /// Gets the first offset >= startOffset where the generator wants to construct
    /// an element.
    /// Return -1 to signal no interest.
    public override int GetFirstInterestedOffset(int startOffset)
    {
        Match m = FindMatch(startOffset);
        return m.Success ? (startOffset + m.Index) : -1;
    }

    /// Constructs an element at the specified offset.
    /// May return null if no element should be constructed.
    public override VisualLineElement ConstructElement(int offset)
    {
        Match m = FindMatch(offset);
        // check whether there's a match exactly at offset
        if (m.Success && m.Index == 0)
        {
            var line = new VisualLineLinkText(CurrentContext.VisualLine, m.Length);

            line.NavigateUri = new Uri("http://google.com");
            return line;
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是有两个问题我似乎无法弄清楚:

  1. 我应该向 VisualLineLinkText 构造函数传递什么来简化文本“MyLink”?

  2. 我应该在哪里放置一个将接收 RequestNavigateEventArgs 的事件处理程序,以便我可以覆盖点击行为?

Ale*_*ins 5

我需要在 AvalonEdit 中使用超链接样式对象,但仅限于“跳转到定义”样式用途,而不是用于 Web 超链接。我不想启动网络浏览器,并且我需要自己在代码中捕获超链接单击事件。

为此,我创建了一个继承自 VisualLineText 的新类。它包含一个 CustomLinkClicked 事件,并将一个字符串传递给事件处理程序。

/// <summary>
/// VisualLineElement that represents a piece of text and is a clickable link.
/// </summary>
public class CustomLinkVisualLineText : VisualLineText
{

    public delegate void CustomLinkClickHandler(string link);

    public event CustomLinkClickHandler CustomLinkClicked;

    private string Link { get; set; }

    /// <summary>
    /// Gets/Sets whether the user needs to press Control to click the link.
    /// The default value is true.
    /// </summary>
    public bool RequireControlModifierForClick { get; set; }

    /// <summary>
    /// Creates a visual line text element with the specified length.
    /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
    /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
    /// </summary>
    public CustomLinkVisualLineText(string theLink, VisualLine parentVisualLine, int length)
        : base(parentVisualLine, length)
    {
        RequireControlModifierForClick = true;
        Link = theLink;
    }


    public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)
    {
        TextRunProperties.SetForegroundBrush(Brushes.GreenYellow);
        TextRunProperties.SetTextDecorations(TextDecorations.Underline);
        return base.CreateTextRun(startVisualColumn, context);
    }

    bool LinkIsClickable()
    {
        if (string.IsNullOrEmpty(Link))
            return false;
        if (RequireControlModifierForClick)
            return (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
        else
            return true;
    }


    protected override void OnQueryCursor(QueryCursorEventArgs e)
    {
        if (LinkIsClickable())
        {
            e.Handled = true;
            e.Cursor = Cursors.Hand;
        }
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Left && !e.Handled && LinkIsClickable())
        {

            if (CustomLinkClicked != null)
            {
                CustomLinkClicked(Link);
                e.Handled = true;
            }

        }
    }

    protected override VisualLineText CreateInstance(int length)
    {

        var a = new CustomLinkVisualLineText(Link, ParentVisualLine, length)
        {                
            RequireControlModifierForClick = RequireControlModifierForClick
        };

        a.CustomLinkClicked += link => ApplicationViewModel.Instance.ActiveCodeViewDocument.HandleLinkClicked(Link);
        return a;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于这些元素是在运行时动态创建和销毁的,因此我必须将单击事件注册到要处理的类的静态实例。

a.CustomLinkClicked += link => ApplicationViewModel.Instance.ActiveCodeViewDocument.HandleLinkClicked(Link);
Run Code Online (Sandbox Code Playgroud)

当您单击链接时(如果指定,请使用 Ctrl 键单击),它将触发该事件。您可以将“Link”字符串替换为您需要的任何其他类。您需要将“ApplicationViewModel.Instance.ActiveCodeViewDocument.HandleLinkClicked(Link)”行替换为您可以在代码中访问的内容。