我正在构建一个自定义控件,根据一些数据执行一些自定义绘图。 我想在排列被调用时更新绘图(即大小被改变)。 但是当我在ArrangeOverride()中改变我的孩子时,我得到一个无限循环。 我怎样才能避免这种情况?
为简单起见,我更容易重建整个可视树而不是创建一次子项并单独调整它们。
有没有更好的方法来做到这一点? 我也可以使用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()}); } }I am building a custom control that does some custom drawing based on some data. I want to update the drawing when arrange is called (i.e. the size is changed). But when I am changing my Children in ArrangeOverride() I get an infinite loop of course. How can I avoid this?
For simplicity it is easier for me to rebuild the whole visual tree instead of creating children once and resizing them individually.
Is there a better approach to do this? I can also live with just using a DrawingContext object and invoking my drawing logic there.
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; } }Here is how I solved it:
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; } }更多推荐
发布评论