2009-11-02 15 views
6

मैं अपना खुद का 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(); 
     } 
    } 
} 

InvalidateVisual() कुछ नहीं करता है:

यहाँ सबसे सरल नमूना है। यद्यपि यदि आप तत्व युक्त विंडो का आकार बदलते हैं, तो यह अपडेट हो जाता है।

सामग्री को सही तरीके से रीफ्रेश करने के तरीके पर कोई विचार? पसंदीदा बिना मेरे तत्व के लिए नई निर्भरता गुणों को प्रस्तुत करना।

उत्तर

7

testControl वर्ग निर्माता को

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

जोड़ें।

+0

यह कोड दृश्य को रिसाव करने का कारण बनता है, क्योंकि यह पेड़ में जोड़ा जाता है, लेकिन कभी नहीं हटाया जाता है। लोड किया गया ईवेंट पर दृश्य जोड़ने के लिए एक बेहतर कोड है, और इसे अनलोड किए गए ईवेंट पर हटाएं - मेरा उत्तर देखें। – splintor

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 बनाने हैं, तो आप फिर से खुल सकते हैं इसे बाद में और परिवर्तन यह आदेशों ड्राइंग है, और वे करेंगे अद्यतन किया जा।

संबंधित मुद्दे