DrawingVisual not updating

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

If I change the contents of the visual image after the initial rendering (for example, in the timer handler) using DrawingVisual.RenderOpen() and drawing to the context, the element is not updated.

Here is the simplest example:

 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 item, it will be updated.

Any ideas on updating content properly? Preferably without , representing new dependency properties for my element.

+6
wpf rendering
source share
3 answers

Add

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

into the constructor of the TestControl class.

+7
source share

Based on the SMART_n answer , this is an improved solution that does not 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); } 
+5
source share

If you create _visual a DrawingGroup , you can re-open it later and change its drawing commands, and they will be updated.

0
source share

All Articles