2009-02-24 8 views
6

estoy usando un Adorner en .NET 3.5, y estoy capaz de dibujar anulando OnRender, pero necesito la capacidad de volver a dibujar el embellecedor para cambiar su apariencia.Animación dentro de un embellecedor (llamando OnRender)

Esencialmente estoy buscando una manera de despejar el contexto de dibujo y llame OnRender nuevo. ¿Cuál es la mejor manera de hacer esto o hay un mejor enfoque?

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

Respuesta

10

La respuesta a su pregunta es utilizar InvalidateVisual para hacer que la OnRender a ser llamado de nuevo

Sin embargo, sugeriría en lugar de hacerlo a medida basándose en OnRender sí mismo para usar el estilo estándar y plantillas árbol visual a construir la visual real del adorno. Esto también significa que puede ejecutar animaciones XAML estándar dentro de él con guiones gráficos.

Si quieres ir con este enfoque, en su clase adorner necesita:

  • en el constructor o bien llamar base.AddVisualChild() o crear su propia colección de imágenes con las imágenes que desea mostrar en el adorner
  • anula ArrangeOverride(Size size) para organizar los niños correctamente;
  • anulación VisualChildrenCount devolver el número de niños en el árbol visual adorner;
  • anula GetCisualChild(int index) para devolver un niño en particular.

Puede echar un vistazo a la muestra MSDN ResizingAdorner para obtener más información.

0

Es muy importante entender que WPF no es como Windows.Forms. OnRender() realmente debería llamarse AccumulateDrawingObjects(), porque eso es lo que está haciendo. WPF acumula un grupo de objetos de dibujo, que retiene para poder dibujar la IU siempre que lo necesite. La magia de la actualización de la interfaz de usuario de manera eficiente es que en realidad se puede cambio objetos de ese árbol visual despuésOnRender().

Por ejemplo, puede hacer un DrawingGroup "backingStore", y ponerlo en el DrawingContext durante OnRender. Luego, cada vez que desee cambiar el aspecto visual, puede DrawingGroup.Open(), poner nuevos comandos de dibujo en él, y WPF volverá a procesar de manera eficiente esa parte de la interfaz de usuario.

Se ve así:

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