2009-04-11 6 views
5

मैं एक कैनवास नियंत्रण बना रहा हूं। इस रूट कैनवास में कई ओवरलैपिंग बच्चे हैं (कैनवास भी)। ऐसा इसलिए किया जाता है ताकि प्रत्येक बच्चा अपनी ड्राइंग को संभाल सके और मैं वांछित व्यवहार प्राप्त करने के लिए बच्चों के किसी भी संयोजन के साथ अंतिम परिणाम लिख सकता हूं।सी # wpf ओवरलैपिंग नियंत्रण माउस ईवेंट प्राप्त नहीं कर रहे हैं

यह बहुत अच्छी तरह से काम कर रहा है जहां तक ​​प्रतिपादन का संबंध है। हालांकि यह माउस घटनाओं के साथ इतना अच्छा काम नहीं करता है। जिस तरह से माउस की घटनाओं काम करता है (एक उदाहरण के रूप previewmousemove का प्रयोग करके) निम्न हैं: जड़ कैनवास, माउस, आग घटना 2- चेक सभी बच्चों के अधीन है

1- अगर एक माउस, आग घटना के अधीन है और

रोक

इस तरह, केवल पहले बच्चे को जो मैं जोड़ता हूं वह माउस मूव इवेंट प्राप्त करेगा। घटना सभी बच्चों के लिए प्रचारित नहीं है क्योंकि वे ओवरलैप करते हैं।

इस पर काबू पाने के लिए, मैं निम्नलिखित का प्रयास किया: जड़ कैनवास 2- हर घटना के लिए में 1- अवहेलना माउस घटनाओं, सभी बच्चों कि VisualTreeHelper.HitTest 3 का उपयोग करके सभी बच्चों के लिए घटना हैंडल करना चाहते हैं लगता है कि एक वैध हिट टेस्ट परिणाम लौटाया (यानी: माउस के नीचे और ईवेंट को संभालने के लिए तैयार (IsHitTestVisible == true)), ???

यह वह जगह है जहां मैं फंस गया हूं, मुझे किसी भी तरह से सभी बच्चों को माउस ईवेंट भेजने की आवश्यकता है, और यह सुनिश्चित करने के लिए घटना के सामान्य प्रवाह को रोकें कि पहले बच्चे को इसे दो बार प्राप्त नहीं होता है (हैंडल = सच में घटना)।

बच्चों पर पारित एक ही घटना के साथ RaiseEvent का उपयोग करके, चीजें काम करने लगती हैं लेकिन किसी भी तरह से यह पेरेंट (रूट कैनवास) पर भी घटना को उठाती है। इसे बाईपास करने के लिए मुझे घटना की एक प्रति बनाने की आवश्यकता थी और सेट को स्रोत सेट करने के लिए सेट किया गया था, हालांकि यह समाधान की तुलना में हैक का अधिक प्रतीत होता है। क्या करने का कोई सही तरीका है जो मैं करने की कोशिश कर रहा हूं? कोड उदाहरण निम्नानुसार है।

public class CustomCanvas : Canvas 
    { 
     private List<object> m_HitTestResults = new List<object>(); 

     public new event MouseEventHandler MouseMove; 

     public CustomCanvas() 
     { 
      base.PreviewMouseMove += new MouseEventHandler(CustomCanvas_MouseMove); 
     } 

     private void CustomCanvas_MouseMove(object sender, MouseEventArgs e) 
     { 
// Hack here, why is the event raised on the parent as well??? 
      if (e.OriginalSource == this) 
      { 
       return; 
      } 

       Point pt = e.GetPosition((UIElement)sender); 
       m_HitTestResults.Clear(); 

       VisualTreeHelper.HitTest(this, 
        new HitTestFilterCallback(OnHitTest), 
        new HitTestResultCallback(OnHitTest), 
        new PointHitTestParameters(pt)); 

       MouseEventArgs tmpe = new MouseEventArgs(e.MouseDevice, e.Timestamp, e.StylusDevice); 
       tmpe.RoutedEvent = e.RoutedEvent; 
       tmpe.Source = this; 

       foreach (object hit in m_HitTestResults) 
       { 
        UIElement element = hit as UIElement; 
        if (element != null) 
        { 
// This somehow raises the event on us as well as the element here, why??? 
         element.RaiseEvent(tmpe); 
        } 
       } 


      var handlers = MouseMove; 
      if (handlers != null) 
      { 
       handlers(sender, e); 
      } 

      e.Handled = true; 
     } 

     private HitTestFilterBehavior OnHitTest(DependencyObject o) 
     { 
      UIElement element = o as UIElement; 
      if (element == this) 
      { 
       return HitTestFilterBehavior.ContinueSkipSelf; 
      } 
      else if (element != null && element.IsHitTestVisible && element != this) 
      { 
       return HitTestFilterBehavior.Continue; 
      } 
      return HitTestFilterBehavior.ContinueSkipSelfAndChildren; 
     } 

     private HitTestResultBehavior OnHitTest(HitTestResult result) 
     { 
      // Add the hit test result to the list that will be processed after the enumeration. 
      m_HitTestResults.Add(result.VisualHit); 
      // Set the behavior to return visuals at all z-order levels. 
      return HitTestResultBehavior.Continue; 
     } 
+0

ध्यान दें कि मुझे रूट कैनवास के बच्चों के बच्चों के अंदर टूलटिप्स के साथ काम करने की भी आवश्यकता होगी। –

+1

क्या यह चांदी की रोशनी के लिए है? WPF? प्रासंगिक टैग जोड़ें, आपको एक उत्तर तेज मिलेगा। – SirDemon

उत्तर

0

मैंने पाया अपने कोड उदाहरण दिलचस्प तो मैं यह एक कोशिश दे दी है ... लेकिन मैं एक छोटा सा संशोधन बनाने के लिए यह मेरा सामान में ठीक से काम करने के लिए किया था।

if (element == null || element.IsHitTestVisible) 

आप देख सकते हैं मैं बेकार निकाला गया "! तत्व = इस" अंत में (आप पहले से ही है कि हालत का परीक्षण किया:

मैं 2 "अगर" इस ​​प्रकार HitTestFilter विधि में बदलना पड़ा पहले "अगर" में) और मैंने शुरुआत में "तत्व == शून्य" जोड़ा।

क्यों? क्योंकि फ़िल्टरिंग के दौरान किसी बिंदु पर पैरामीटर प्रकार System.Windows.Media.ContainerVisual था जो UIElement से प्राप्त नहीं होता है और इसलिए तत्व शून्य पर सेट हो जाएगा और जारी रखें और जारी रखें बच्चे को वापस कर दिया जाएगा। लेकिन मैं बच्चों को छोड़ना नहीं चाहता क्योंकि मेरा कैनवास अपने "बच्चों" संग्रह और UIElements के अंदर निहित है, जिसके साथ मैं कैनवास में निहित होना चाहता हूं।

3

मुझे लगता है कि आपको पूर्वावलोकन ईवेंट का उपयोग करना चाहिए क्योंकि वे रूटिंगस्ट्रेटी हैं। ज़ूम-ऑर्डर में विंडो से सबसे ज्यादा नियंत्रण में सुरंग, और सामान्य घटनाएं RoutingStrategy.Bubble हैं।

इस रूटेड एवेन्ट्स में एक संपत्ति हैंडल होती है जब यह सच है कि सिस्टम दृश्य पेड़ को पार करने के लिए बंद हो जाएगा क्योंकि किसी ने इस घटना का उपयोग किया था।

0

जैसा कि @GuerreroTook ने कहा था, आपको WPF के रूटेड एवेन्ट्स (अधिक जानकारी here का उपयोग करके इसे हल करना चाहिए।