WPF自定义控件绘图避免无限测量/排列循环(WPF Custom Control drawing avoid infinite measure/arrange loop)

编程入门 行业动态 更新时间:2024-10-26 14:31:45
WPF自定义控件绘图避免无限测量/排列循环(WPF Custom Control drawing avoid infinite measure/arrange loop)

我正在构建一个自定义控件,根据一些数据执行一些自定义绘图。 我想在排列被调用时更新绘图(即大小被改变)。 但是当我在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; } }

更多推荐

本文发布于:2023-07-16 13:32:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1129045.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   控件   排列   测量   Custom

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!