2009-11-02 46 views
6

我創建我自己的FrameworkElement,並通過返回我自己的DrawingVisual實例覆蓋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(); 
     } 
    } 
} 

InvalidateVisual()什麼都不做。儘管如果您調整包含元素的窗口大小,它會被更新。

關於如何正確刷新內容的任何想法?最好是而不是爲我的元素引入新的依賴項屬性。

回答

7

添加

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

系統testControl到類的構造函數。

+0

此代碼會導致視覺泄漏內存,因爲它被添加到樹中,但從未刪除。更好的代碼是在Loaded事件上添加視覺,並在Unloaded事件中刪除它 - 請參閱我的答案。 – splintor 2012-06-17 16:23:14

5

基於SMART_n's answer,這裏是不漏的改進方案記憶:

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

如果您_visual一個DrawingGroup,您可以稍後重新打開它,改變它的繪圖命令,他們將被更新。