2009-02-24 11 views
6

Utilizzo un Adorner in .NET 3.5 e sono in grado di disegnare eseguendo l'override di OnRender, ma ho bisogno della possibilità di ridisegnare l'adorner per modificarne l'aspetto.Animazione all'interno di un adorner (chiamata OnRender)

In sostanza sto cercando un modo per cancellare il contesto di disegno e chiamare di nuovo OnRender. Qual è il modo migliore per farlo, o c'è un approccio migliore?

public class MyAdorner : Adorner 
{ 
    private Brush brush = Brushes.Red; 

    public DragArrowAdorner(UIElement adornedElement) : base(adornedElement) 
    {} 

    public void RedrawWithBrush(Brush newBrush) 
    { 
     brush = newBrush; 

     // redraw..? 
    } 

    protected override void OnRender(System.Windows.Media.DrawingContext drawingContext) 
    { 
     // some drawing code... 
     drawingContext.DrawRectangle(
      brush, 
      null, 
      new Rect(AdornedElement.DesiredSize)); 
    } 
} 

risposta

10

La risposta alla tua domanda è utilizzare InvalidateVisual per causare l'OnRender di essere chiamato di nuovo

Tuttavia, vorrei suggerire invece di fare personalizzato attingendo OnRender te stesso per utilizzare lo stile standard ed albero di template visivo costruire la visuale reale dell'ornatore. Ciò significa anche che è possibile eseguire animazioni XAML standard al suo interno con storyboard.

Se si vuole andare con questo approccio, nella tua classe adorner è necessario:

  • nel costruttore o chiamare base.AddVisualChild() o creare la propria collezione grafica con le immagini che si desidera visualizzare nel adorner
  • override ArrangeOverride(Size size) per organizzare correttamente i bambini;
  • override VisualChildrenCount per restituire il numero di figli nell'albero di visualizzazione adornatore;
  • override GetCisualChild(int index) per restituire un determinato bambino.

È possibile dare un'occhiata al campione MSDN ResizingAdorner per ulteriori informazioni.

0

È molto importante capire che WPF non è come Windows.Forms. OnRender() dovrebbe davvero essere chiamato AccumulateDrawingObjects(), perché è quello che sta facendo. WPF accumula un sacco di oggetti di disegno, che conserva per essere in grado di disegnare l'interfaccia utente ogni volta che è necessario. La magia di aggiornare in modo efficiente l'interfaccia utente è che è possibile effettivamente modificare gli oggetti nell'albero visivo dopoOnRender().

Ad esempio, è possibile creare un "backingStore" DrawingGroup e inserirlo nello DrawingContext durante OnRender. Quindi, ogni volta che si desidera modificare l'aspetto visivo, è possibile eseguire DrawingGroup.Open(), inserire nuovi comandi di disegno e WPF restituirà in modo efficiente quella parte dell'interfaccia utente.

Ecco come si presenta:

DrawingGroup backingStore = new DrawingGroup(); 

protected override void OnRender(DrawingContext drawingContext) {  
    base.OnRender(drawingContext);    

    Render(); // put content into our backingStore 
    drawingContext.DrawDrawing(backingStore); 
} 

// I can call this anytime, and it'll update my visual drawing 
// without ever triggering layout or OnRender() 
private void Render() {    
    var drawingContext = backingStore.Open(); 
    Render(drawingContext); 
    drawingContext.Close();    
}