2010-11-18 17 views
5

Ho una forma di linea personalizzata che utilizza un dispositivo di decorazione per visualizzare una matrice e del testo al centro di tale linea.Adorner ed eventi su Elemento ornato

alt text

Il problema è che il adornata comporta indipendentemente dall'elemento ornato, e non "transfer" l'evento ad esso. Nel codice seguente sono costretto a ricollegare manualmente gli elementi decorativi all'elemento decorato (ta.MouseLeftButtonDown += Adorner_MouseLeftButtonDown;), ma sfortunatamente anche questo non funziona ... Qualcuno potrebbe consigliare cosa non va quando lo chiama.OnMouseLeftButtonDown, perché non ricevo il rispettivo evento?

public class SegmentLine : Shape 
{ 
    AdornerLayer aLayer; 

    public static readonly DependencyProperty X1Property; 
    public static readonly DependencyProperty X2Property; 
    public static readonly DependencyProperty Y1Property; 
    public static readonly DependencyProperty Y2Property; 
    ... 

    static SegmentLine() { 
     X1Property = DependencyProperty.Register("X1", typeof(double), typeof(SegmentLine), new FrameworkPropertyMetadata(double.NaN, 
      FrameworkPropertyMetadataOptions.AffectsRender)); 
     X2Pro... 
    } 

    public SegmentLine() 
     : base() 
    { 
     this.Loaded += SegmentLine_Loaded; 
    } 

    void SegmentLine_Loaded(object sender, RoutedEventArgs e) 
    { 
     aLayer = AdornerLayer.GetAdornerLayer(this); 
     if (aLayer != null) 
     { 
      TextAdorner ta = new TextAdorner(this); 
      //ta.IsHitTestVisible = false; 
      ta.MouseLeftButtonDown += Adorner_MouseLeftButtonDown; 
      aLayer.Add(ta); 
     } 
    } 

    void Adorner_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     // !! try to rise the MouseLeftButtonDown event 
     this.OnMouseLeftButtonDown(e); 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 
     if (aLayer != null) 
      aLayer.Update(); 
    } 

    class TextAdorner : Adorner 
    { 
     public TextAdorner(UIElement adornedElement) 
      : base(adornedElement) { } 

     protected override void OnRender(DrawingContext drawingContext) 
     { 
      // ADD LABEL ... 
      FormattedText ft = new FormattedText(...); 
      drawingContext.DrawText(ft, midPoint); 

      // Add ARROW ... 
      var myPathGeometry = new PathGeometry { Figures = myPathFigureCollection };    
      drawingContext.DrawGeometry(Brushes.Black, null, myPathGeometry); 
     } 
    } 

    protected override System.Windows.Media.Geometry DefiningGeometry 
    { 
     get 
     { 
      var geometryGroup = new GeometryGroup(); 
      // Add line 
      geometryGroup.Children.Add(new LineGeometry(new Point(X1, Y1), new Point(X2, Y2))); 
      return geometryGroup; 
     } 
    }  
} 
+1

È possibile disabilitare tutti gli eventi su adorner semplicemente impostando 'IsHitTestVisible' su false. O vuoi che alcuni eventi siano gestiti da Adorner e altri da 'SegmentLine'? –

+0

@ alpha-mouse: no, qualsiasi evento che voglio essere gestito da adorner, ma se imposto solo IsHitTestVisible = false (come puoi vedere commentato nel codice) non ricevo affatto eventi. – serhio

risposta

5

Si dovrebbe chiamare this.RaiseEvent(e); invece di this.OnMouseLeftButtonDown(e); di trasferire l'evento all'elemento ornata.
E, a proposito, è possibile utilizzare un solo gestore di eventi per trasferire diversi tipi di evento

void SegmentLine_Loaded(object sender, RoutedEventArgs e) 
{ 
    .. 
    ta.MouseLeftButtonDown += Adorner_AnyEvent; 
    ta.MouseRightButtonDown += Adorner_AnyEvent; 
} 

void Adorner_AnyEvent(object sender, RoutedEventArgs e) 
{ 
    this.RaiseEvent(e); 
} 
1

So che questo è vecchio, ma ho avuto un problema simile (che non ricevono gli eventi in Adorner), che ho fissato disegnando uno sfondo trasparente nel mio OnRender()

drawingContext.DrawRectangle(Brushes.Transparent, null, viewRect); 

Nessun background = nessun evento.