DrawingVisual未刷新

rep*_*pka 7 wpf rendering

我创建自己的FrameworkElement并覆盖VisualChildrenCount{get;}GetVisualChild(int index)返回我自己的DrawingVisual实例.

如果我在初始渲染后(例如在计时器处理程序中)使用DrawingVisual.RenderOpen()和绘制到上下文中修改视觉内容,则不刷新元素.

这是最简单的样本:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

namespace VisualTest
{
    public class TestControl : FrameworkElement
    {
        private readonly DrawingVisual _visual = new DrawingVisual();

        public TestControl()
        {
            Draw(false);

            var timer = new DispatcherTimer {Interval = new TimeSpan(0, 0, 2)};
            timer.Tick += (sender, args) =>
                              {
                                  Draw(true);
                                  InvalidateVisual();
                                  timer.Stop();
                              };
            timer.Start();
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visual;
        }

        protected override int VisualChildrenCount
        {
            get { return 1; }
        }

        private void Draw(bool second)
        {
            DrawingContext ctx = _visual.RenderOpen();
            if (!second)
                ctx.DrawRoundedRectangle(Brushes.Green, null, new Rect(0, 0, 200, 200), 20, 20);
            else
                ctx.DrawEllipse(Brushes.Red, null, new Point(100, 100), 100, 100);
            ctx.Close();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

InvalidateVisual()什么也没做.虽然如果您调整包含该元素的窗口的大小,它会更新.

有关如何正确刷新内容的任何想法?最好不要为我的元素引入新的依赖属性.

SMA*_*T_n 9

this.AddVisualChild(_visual);
this.AddLogicalChild(_visual);
Run Code Online (Sandbox Code Playgroud)

到TestControl类的构造函数.


spl*_*tor 6

基于SMART_n的答案,这是一个不会泄漏内存的改进解决方案:

    public TestControl()
    {
        Loaded += AddVisualToTree;
        Unloaded += RemoveVisualFromTree;

        Draw(false);

        var timer = new DispatcherTimer {Interval = new TimeSpan(0, 0, 2)};
        timer.Tick += (sender, args) =>
                          {
                              Draw(true);
                              InvalidateVisual();
                              timer.Stop();
                          };
        timer.Start();

    }

    private void AddVisualToTree(object sender, RoutedEventArgs e)
    {
        AddVisualChild(_visual);
        AddLogicalChild(_visual);
    }

    private void RemoveVisualFromTree(object sender, RoutedEventArgs e)
    {
        RemoveLogicalChild(_visual);
        RemoveVisualChild(_visual);
    }
Run Code Online (Sandbox Code Playgroud)