2015-02-07 2 views
1

AvalonEdit을 사용하여 사용자 지정 하이퍼 링크를 만들려고합니다. 나는 구문을 인식 (샘플 기준) 발전기를 만들었습니다와 나는 열린 우리당을 설정할 수 있습니다AvalonEdit을 사용한 사용자 지정 하이퍼 링크

  1. :

    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; 
        } 
    } 
    

    그러나 내가 알아낼 수없는 것 두 가지 문제가 있습니다

    "MyLink"라고 말하는 텍스트를 단순화하기 위해 VisualLineLinkText 생성자로 전달할 대상은 무엇입니까?

  2. 클릭 동작을 재정의 할 수 있도록 RequestNavigateEventArgs를받을 이벤트 핸들러를 어디에 두어야합니까?

답변

2

AvalonEdit에서 하이퍼 링크 스타일 개체를 사용해야했지만 웹 하이퍼 링크가 아닌 '점프로 정의'스타일에서만 사용하고있었습니다. 웹 브라우저가 시작되기를 원치 않았고 코드에서 하이퍼 링크 클릭 이벤트를 직접 잡아야했습니다.

이 목적을 위해 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; 
    } 
} 

, 내가 처리 할 수있는 클래스의 정적 인스턴스에 클릭 이벤트를 등록했다.

a.CustomLinkClicked += link => ApplicationViewModel.Instance.ActiveCodeViewDocument.HandleLinkClicked(Link); 

링크를 클릭하면 (지정된 경우 Ctrl 키를 누른 상태에서 클릭) 이벤트를 발생시킵니다. "Link"문자열은 필요한 다른 클래스로 바꿀 수 있습니다. 'ApplicationViewModel.Instance.ActiveCodeViewDocument.HandleLinkClicked (Link)'행을 코드에서 액세스 할 수있는 행으로 바꿔야합니다.

+0

"Jump To Definition"스타일의 네비게이션은 정확하게 달성하려고 노력하고 있습니다. VisualLineText 사용시 "일치"가 발생하는 곳을 알 수 없습니다. 어떻게하면 하이라이팅 엔진에 연결할 수 있습니까? – themightylc

+0

위의 의견을 무시하십시오. 구문 강조 CreateInstance Sub에서 발생합니다. – themightylc

관련 문제