2009-02-24 2 views
6

Я использую Adorner в .NET 3.5, и я могу рисовать, переопределяя OnRender, но мне нужна возможность перерисовать рекламодателя, чтобы изменить его внешний вид.Анимация внутри рекламодателя (вызов OnRender)

По сути, я ищу способ очистить контекст чертежа и снова вызвать OnRender. Каков наилучший способ сделать это, или есть лучший подход?

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

ответ

10

Ответ на ваш вопрос заключается в использовании InvalidateVisual, чтобы заставить OnRender называться снова

Однако, я хотел бы предложить вместо делать заказ, опираясь на OnRender себя использовать стандартный стиль и визуальный дерево шаблонов для выстроить реальный визуальный эффект у adorner. Это также означает, что вы можете запускать стандартные анимации XAML внутри него с помощью раскадровки.

Если вы хотите, чтобы пойти с этим подходом, в классе Adorner вам нужно:

  • в конструкторе или вызвать base.AddVisualChild() или создать свою собственную коллекцию визуальных с визуальными вы хотите показать в Adorner
  • переопределить ArrangeOverride(Size size), чтобы правильно расположить детей;
  • переопределить VisualChildrenCount, чтобы вернуть количество детей в визуальное дерево adorner;
  • переопределить GetCisualChild(int index), чтобы вернуть определенного ребенка.

Вы можете ознакомиться с образцом MSDN ResizingAdorner для получения дополнительной информации.

0

Очень важно понять, что WPF не похож на Windows.Forms. OnRender() действительно следует называть AccumulateDrawingObjects(), потому что это то, что он делает. WPF накапливает кучу чертежных объектов, которые он сохраняет, чтобы иметь возможность рисовать пользовательский интерфейс, когда это необходимо. Магия эффективного обновления пользовательского интерфейса состоит в том, что вы можете на самом деле изменить объекты в этом визуальном дереве послеOnRender().

Например, вы можете сделать DrawingGroup "backingStore", и положите его в DrawingContext во время OnRender. Затем в любое время, когда вы хотите изменить визуал, вы можете DrawingGroup.Open(), поместить в него новые команды рисования, и WPF будет эффективно повторно отображать эту часть пользовательского интерфейса.

Это выглядит следующим образом:

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

 Смежные вопросы

  • Нет связанных вопросов^_^