我使用的是.NET 3.5中的装饰器,我可以通过覆盖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));
}
}发布于 2009-02-24 22:34:23
您的问题的答案是使用InvalidateVisual再次调用OnRender
但是,我建议您使用标准样式和可视化树模板来构建装饰器的实际视觉效果,而不是自己在OnRender上进行自定义绘制。这也意味着你可以用故事板在它里面运行标准的XAML动画。
如果你想使用这种方法,在你的装饰器类中,你需要:
构造函数中的视觉效果可以调用base.AddVisualChild(),也可以使用要在adorner
VisualChildrenCount中显示的视觉效果创建您自己的视觉效果集合,以便安排子对象properly;
base.AddVisualChild()以返回装饰器视觉效果ArrangeOverride(Size size) VisualChildrenCount中的子对象数,从而返回特定的子对象。您可以查看ResizingAdorner MSDN示例以获取更多信息。
发布于 2017-06-10 15:41:10
理解WPF不同于Windows.Forms是非常重要的。OnRender()实际上应该被称为AccumulateDrawingObjects(),因为它就是这么做的。WPF累积了一组绘图对象,它保留了这些对象,以便能够在需要时绘制UI。高效更新UI的神奇之处在于,在OnRender()之后,您实际上可以更改该可视化树中的对象。
例如,您可以将DrawingGroup设置为"backingStore",并在OnRender期间将其放入DrawingContext中。然后,当您想要更改视觉效果时,您可以使用DrawingGroup.Open(),将新的绘图命令放入其中,WPF将有效地重新呈现UI的这一部分。
它看起来是这样的:
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();
}https://stackoverflow.com/questions/583808
复制相似问题