2009-02-24 2 views
6

Ich benutze einen Adorner in .NET 3.5, und ich kann zeichnen, indem ich OnRender überschreibe, aber ich brauche die Fähigkeit, den Adorner neu zu zeichnen, um sein Aussehen zu ändern.Animation in einem Adorner (Aufruf von OnRender)

Im Wesentlichen bin ich auf der Suche nach einer Möglichkeit, den Zeichnungskontext zu löschen und OnRender wieder aufzurufen. Was ist der beste Weg dies zu tun, oder gibt es einen besseren Ansatz?

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

Antwort

10

Die Antwort auf Ihre Frage ist InvalidateVisual verwendet die OnRender um zu bewirken, wieder

jedoch genannt werden, würde ich vorschlagen, anstatt individuelle tun OnRender selbst zeichnet auf, um das Standard-Design und visuelle Struktur Templat zu verwenden, um baue das eigentliche Visuelle des Adorters auf. Dies bedeutet auch, dass Sie mit Storyboards Standard-XAML-Animationen darin ausführen können.

Wenn Sie mit diesem Ansatz gehen wollen, in Ihrem adorner Klasse müssen Sie:

  • im Konstruktor entweder base.AddVisualChild() aufrufen oder eigene Visuals Sammlung erstellen mit den Visuals Sie in der adorner zeigen wollen
  • übersteuern ArrangeOverride(Size size), um die Kinder richtig anzuordnen;
  • überschreiben VisualChildrenCount, um die Anzahl der untergeordneten Elemente im visuellen Baum des Adorners zurückzugeben;
  • überschreiben GetCisualChild(int index), um ein bestimmtes Kind zurückgeben.

Sie können für weitere Informationen an die ResizingAdorner MSDN Probe einen Blick darauf werfen.

0

Es ist sehr wichtig zu verstehen, dass WPF nicht wie Windows.Forms ist. OnRender() sollte wirklich AccumulateDrawingObjects() genannt werden, weil das ist, was es tut. WPF akkumuliert eine Reihe von Zeichnungsobjekten, die es behält, die Benutzeroberfläche bei Bedarf zeichnen zu können. Die Magie der effizienten Aktualisierung der Benutzeroberfläche ist, dass Sie Objekte in diesem visuellen Baum nachOnRender() ändern können.

Zum Beispiel können Sie eine DrawingGroup "backingStore", und setzen Sie diese in die DrawingContext während OnRender. Dann können Sie, wann immer Sie das visuelle Element ändern möchten, DrawingGroup.Open() neue Zeichenbefehle einfügen und WPF wird diesen Teil der Benutzeroberfläche effizient neu rendern.

Es sieht wie folgt aus:

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