2014-12-25 5 views
0

richtextbox에서 임의의 텍스트 범위에 대한 툴팁을 설정하려고합니다. 이것이 가능한가? 그렇다면 어떻게하면 "from"및 "to"매개 변수를 (int) 인덱스로 전달하여 어떻게 처리 할 수 ​​있습니까?wpf richtextbox의 텍스트 범위에 툴팁 설정

감사

+0

코드 숨김에서 이벤트를 처리하는 http://stackoverflow.com/questions/5928809/show-tooltip-on-richtextbox 기반 솔루션이있을 수 있습니다. –

답변

0

당신은 출발점으로 다음 사용할 수 있습니다

  1. System.Windows.Interactivity에 대한 참조를 추가합니다.

  2. 프로젝트에 다음 클래스를 추가

    public class TextRangeToolTip 
    { 
        public int StartPosition { get; set; } 
    
        public int Length { get; set; } 
    
        public object ToolTip { get; set; } 
    
        internal bool IsInRange(int position) 
        { 
         return this.StartPosition <= position && position < this.StartPosition + this.Length; 
        } 
    } 
    
    public class TextRangeToolTipCollection : ObservableCollection<TextRangeToolTip> {} 
    
    [ContentProperty("Ranges")] 
    public class ToolTipBehavior : Behavior<RichTextBox> 
    { 
        private const int ToolTipHideMouseDelta = 9; 
    
        public static readonly DependencyProperty RangesProperty 
         = DependencyProperty.Register("Ranges", typeof(TextRangeToolTipCollection), 
                 typeof (ToolTipBehavior), 
                 new PropertyMetadata(OnRangesChanged)); 
    
        private readonly DispatcherTimer timer; 
    
        private readonly ToolTip toolTip; 
        private Point lastMousePosition; 
    
        public TextRangeToolTipCollection Ranges 
        { 
         get 
         { 
          return (TextRangeToolTipCollection)this.GetValue(RangesProperty) 
            ?? (this.Ranges = new TextRangeToolTipCollection()); 
         } 
         set { this.SetValue(RangesProperty, value); } 
        } 
    
        public ToolTipBehavior() 
        { 
         this.Ranges = new TextRangeToolTipCollection(); 
    
         this.timer = new DispatcherTimer(); 
         this.timer.Tick += this.TimerOnTick; 
         this.timer.Interval = TimeSpan.FromSeconds(1); 
    
         this.toolTip = new ToolTip {Placement = PlacementMode.Relative}; 
        } 
    
        protected override void OnAttached() 
        { 
         this.AssociatedObject.ToolTip = this.toolTip; 
         this.toolTip.PlacementTarget = this.AssociatedObject; 
         ToolTipService.SetIsEnabled(this.AssociatedObject, false); 
    
         this.AssociatedObject.MouseMove += this.AssociatedObjectOnMouseMove; 
        } 
    
        protected override void OnDetaching() 
        { 
         this.timer.Stop(); 
    
         this.toolTip.PlacementTarget = null; 
         this.AssociatedObject.ToolTip = null; 
         this.AssociatedObject.ClearValue(ToolTipService.IsEnabledProperty); 
    
         this.AssociatedObject.MouseMove -= this.AssociatedObjectOnMouseMove; 
        } 
    
        private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs) 
        { 
         Point currentMousePosition = mouseEventArgs.GetPosition(this.AssociatedObject); 
    
         if (this.AssociatedObject.IsMouseCaptured) 
         { 
          Vector delta = currentMousePosition 
              - this.lastMousePosition; 
    
          if (delta.X*delta.X + delta.Y*delta.Y <= ToolTipHideMouseDelta) 
          { 
           this.toolTip.HorizontalOffset = currentMousePosition.X + 10; 
           this.toolTip.VerticalOffset = currentMousePosition.Y + 10; 
           return; 
          } 
    
          this.AssociatedObject.ReleaseMouseCapture(); 
          this.toolTip.IsOpen = false; 
         } 
    
         if (this.AssociatedObject.IsMouseOver) 
         { 
          this.lastMousePosition = currentMousePosition; 
          this.timer.Stop(); 
          this.timer.Start(); 
         } 
        } 
    
        private static void OnRangesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
         ((ToolTipBehavior) d).OnRangesChanged((IEnumerable<TextRangeToolTip>) e.OldValue, 
                   (IEnumerable<TextRangeToolTip>) e.NewValue); 
        } 
    
        private void OnRangesChanged(IEnumerable<TextRangeToolTip> oldRanges, IEnumerable<TextRangeToolTip> newRanges) 
        { 
         var oldObservable = oldRanges as INotifyCollectionChanged; 
         if (oldObservable != null) 
         { 
          CollectionChangedEventManager.RemoveHandler(oldObservable, this.OnRangesCollectionChanged); 
         } 
    
         var newObservable = newRanges as INotifyCollectionChanged; 
         if (newObservable != null) 
         { 
          CollectionChangedEventManager.AddHandler(newObservable, this.OnRangesCollectionChanged); 
         } 
    
         this.UpdateToolTip(); 
        } 
    
        private void OnRangesCollectionChanged(
         object sender, 
         NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
        { 
         this.UpdateToolTip(); 
        } 
    
        private bool SetToolTipData() 
        { 
         if (this.Ranges == null) 
         { 
          return false; 
         } 
    
         TextPointer pointer = this.AssociatedObject.GetPositionFromPoint(this.lastMousePosition, false); 
         if (pointer == null) 
         { 
          return false; 
         } 
    
         int position = this.AssociatedObject.Document.ContentStart.GetOffsetToPosition(pointer); 
    
         TextRangeToolTip matchingRange = this.Ranges.FirstOrDefault(r => r.IsInRange(position)); 
         if (matchingRange == null) 
         { 
          return false; 
         } 
    
         this.toolTip.Content = matchingRange.ToolTip; 
         return true; 
        } 
    
        private void TimerOnTick(object sender, EventArgs eventArgs) 
        { 
         this.timer.Stop(); 
    
         if (this.AssociatedObject.IsMouseOver && this.SetToolTipData()) 
         { 
          this.toolTip.IsOpen = true; 
          this.AssociatedObject.CaptureMouse(); 
         } 
        } 
    
        private void UpdateToolTip() 
        { 
         if (this.AssociatedObject != null && this.AssociatedObject.IsMouseCaptured && !this.SetToolTipData()) 
         { 
          this.toolTip.IsOpen = false; 
          this.AssociatedObject.ReleaseMouseCapture(); 
         } 
        } 
    } 
    
  3. 이처럼 RichTextBox에 그것을 사용

    <RichTextBox> 
        <i:Interaction.Behaviors> 
         <myapp:ToolTipBehavior> 
          <myapp:TextRangeToolTip StartPosition="10" Length="4" ToolTip="some" /> 
          <myapp:TextRangeToolTip StartPosition="15" Length="4" ToolTip="text" /> 
         </myapp:ToolTipBehavior> 
        </i:Interaction.Behaviors> 
        <FlowDocument> 
         <Paragraph>This is some text. This is some other text.</Paragraph> 
        </FlowDocument> 
    </RichTextBox> 
    

    또한,이 같은 TextRangeToolTipCollectionRanges 속성을 바인딩 할 수 있습니다 :

    <RichTextBox Document="{Binding Document}"> 
        <i:Interaction.Behaviors> 
         <myapp:ToolTipBehavior Ranges="{Binding RangeToolTips}" /> 
        </i:Interaction.Behaviors> 
    </RichTextBox> 
    

WPF는 문자가 아닌 기호를 계산하므로 위치를 올바르게 가져 오는 것은 약간 까다 롭습니다. 또는 TextRange 유형의 특성을 갖도록 TextRangeToolTip 클래스를 확장하고 FlowDocument 인스턴스를 사용하여 구성 할 수 있습니다.