我正在构建一个自定义控件,根据一些数据进行一些自定义绘图。我想更新图纸时,安排被称为(即大小改变)。但是当我在ArrangeOverride()中改变我的Children时,我当然会得到一个无限循环。我怎样才能避免这种情况呢?
为了简单起见,对我来说重建整个视觉树更容易,而不是一次创建子节点并单独调整它们的大小。
有更好的方法吗?我也可以只使用DrawingContext对象并在那里调用我的绘图逻辑。
public class MyCanvas : Canvas
{
private static int _drawCounter = 0;
private System.Windows.Size _arrangeSize;
private MyData _data;
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
_arrangeSize = arrangeSize;
Draw();
return base.ArrangeOverride(arrangeSize);
}
public void SetData(MyData data)
{
_data = data;
Draw();
}
private void Draw()
{
Children.Clear();
if (_data == null || _arrangeSize.IsEmpty)
{
return;
}
Children.Add(new TextBlock() {Text = (++_drawCounter).ToString()});
}
}
我是这样解决的:
public class MyCanvas : Canvas
{
private readonly DispatcherTimer _dispatcherTimer;
private Size _arrangeSize;
private Size _drawnSize;
public MyCanvas()
{
_dispatcherTimer = new DispatcherTimer(DispatcherPriority.Render)
{
Interval = TimeSpan.FromMilliseconds(500)
};
_dispatcherTimer.Tick += (sender, args) =>
{
var dispatcherTimer = (DispatcherTimer)sender;
dispatcherTimer.Stop();
Debug.WriteLine("Draw call from DispatcherTimer");
Draw();
};
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
_arrangeSize = arrangeSize;
if (_drawnSize != _arrangeSize)
{
QueueDrawCall();
}
return base.ArrangeOverride(arrangeSize);
}
private void QueueDrawCall()
{
if (_dispatcherTimer.IsEnabled)
{
_dispatcherTimer.Stop();
}
_dispatcherTimer.Start();
}
public void SetData(MyData data)
{
_data = data;
Console.WriteLine("Direct Draw Call " + data);
Draw();
}
private void Draw()
{
if (Children.Count > 0)
{
Children.Clear();
}
if (_data == null || _arrangeSize.IsEmpty)
{
return;
}
InternalDraw(); // Drawing logic goes in this function
_drawnSize = _arrangeSize;
}
}