Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DrawingVisual is not refreshed

Tags:

wpf

rendering

I create my own FrameworkElement and override VisualChildrenCount{get;} and GetVisualChild(int index) by returning my own DrawingVisual instance.

If I modify the content of the visual after initial rendering (e.g. in timer handler) using DrawingVisual.RenderOpen() and drawing into the context, the element is not refreshed.

Here's the simplest sample:

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();
        }
    }
}

InvalidateVisual() does nothing. Although if you resize the window containing the element, it gets updated.

Any ideas on how to properly refresh the content? Preferably without introducing new dependency properties for my element.

like image 353
repka Avatar asked Nov 02 '09 18:11

repka


People also ask

What is drawingvisual object in Visual Studio?

DrawingVisual Object The DrawingVisualis a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art. DrawingVisual Host Container

Is the content of the drawingvisual class persistent?

The content is persisted by the system. DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout, input, focus, or event handling, which improves its performance. For this reason, drawings are ideal for backgrounds and clip art.

Why can't I use the host container object with drawingvisual?

The host container object must be derived from the FrameworkElement class, which provides the layout and event handling support that the DrawingVisual class does not support. The host container object does not display any visual properties, since its main purpose is to contain child objects. For more information, see Using DrawingVisual Objects.

What happens when you refresh data in a dataset?

Whenever you refresh data in a dataset, whether by using Refresh Now or by setting up a refresh schedule, Power BI uses information in the dataset to connect to the data sources defined for it, query for updated data, and then loads the updated data into the dataset.


2 Answers

Add

this.AddVisualChild(_visual);
this.AddLogicalChild(_visual);

to TestControl class constructor.

like image 149
SMART_n Avatar answered Sep 27 '22 19:09

SMART_n


Based on SMART_n's answer, here is an improved solution that doesn't leak memory:

    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);
    }
like image 32
splintor Avatar answered Sep 27 '22 18:09

splintor