2010-05-26 14 views
12

के साथ संयोजन में नहीं खींचता है मेरे पास स्लाइडर के लिए IsMoveToPointEnabled है, इसलिए जब मैं घटक पर कहीं भी क्लिक करता हूं तो चयनकर्ता मेरे माउस पर जाता है। समस्या यह है कि यदि मेरे पास यह विकल्प है और चयनकर्ता को खींचने के लिए माउस को क्लिक करके दबाए रखें तो चयनकर्ता नहीं चलता है। क्या किसी को पता है कि इसे किस प्रकार ठीक किया जा सकता है?स्लाइडर IsMoveToPointEnabled व्यवहार

public class CustomSlider : Slider 
{ 
    public override void OnPreviewMouseMove(MouseEventArgs e) 
    { 
    if(e.LeftButton == MouseButtonState.Pressed) 
     OnPreviewMouseLeftButtonDown(e); 
    } 
} 

जो मामले में अपने XAML होगा::

<my:CustomSlider IsMoveToPointEnabled="True" /> 

एक अधिक बहुमुखी समाधान है कि स्लाइडर के साथ आप यह कर सकते हैं उपवर्ग नहीं करता

उत्तर

17

सबसे आसान तरीका स्लाइडर उपवर्ग है एक संलग्न संपत्ति:

public class SliderTools : DependencyObject 
{ 
    public static bool GetMoveToPointOnDrag(DependencyObject obj) { return (bool)obj.GetValue(MoveToPointOnDragProperty); } 
    public static void SetMoveToPointOnDrag(DependencyObject obj, bool value) { obj.SetValue(MoveToPointOnDragProperty, value); } 
    public static readonly DependencyProperty MoveToPointOnDragProperty = DependencyProperty.RegisterAttached("MoveToPointOnDrag", typeof(bool), typeof(SliderTools), new PropertyMetadata 
    { 
    PropertyChangedCallback = (obj, changeEvent) => 
    { 
     var slider = (Slider)obj; 
     if((bool)changeEvent.NewValue) 
     slider.MouseMove += (obj2, mouseEvent) => 
     { 
      if(mouseEvent.LeftButton == MouseButtonState.Pressed) 
      slider.RaiseEvent(new MouseButtonEventArgs(mouseEvent.MouseDevice, mouseEvent.Timestamp, MouseButton.Left) 
      { 
       RoutedEvent = UIElement.PreviewMouseLeftButtonDownEvent, 
       Source = mouseEvent.Source, 
      }); 
     }; 
    } 
    }); 
} 

आप इस संलग्न संपत्ति का उपयोग स्लाइडर पर IsMov के साथ करेंगे eToPointEnabled संपत्ति:

<Slider IsMoveToPointEnabled="True" my:SliderTools.MoveToPointOnDrag="True" ... /> 

इन समाधानों काम के दोनों बराबर PreviewMouseLeftButtonDown घटनाओं में PreviewMouseMove घटनाओं को परिवर्तित करने के लिए जब भी बाएं बटन नीचे है द्वारा।

ध्यान दें कि जब संपत्ति गलत पर सेट की जाती है तो अटैचमेंट प्रॉपर्टी ईवेंट हैंडलर को नहीं हटाती है। मैंने सादगी के लिए इसे इस तरह लिखा है क्योंकि आपको लगभग इस तरह के हैंडलर को हटाने की आवश्यकता नहीं होगी। मैं आपको इस सरल समाधान के साथ चिपकने की सलाह देता हूं, लेकिन यदि आप चाहते हैं कि जब आप न्यूवैल्यू झूठ बोलते हैं तो हैंडलर को हटाने के लिए आप PropertyChangedCallback को संशोधित कर सकते हैं।

mySlider.PreviewMouseMove += (sender, args) => 
{ 
    if (args.LeftButton == MouseButtonState.Pressed) 
    { 
     mySlider.RaiseEvent(new MouseButtonEventArgs(args.MouseDevice, args.Timestamp, MouseButton.Left) 
     { 
      RoutedEvent = UIElement.PreviewMouseLeftButtonDownEvent, 
       Source = args.Source 
     }); 
    } 
}; 
mySlider मेरी स्लाइडर के नाम जा रहा है

:

+0

धन्यवाद रे! मुझे लगता है कि मैं लगभग यह काम कर रहा है। मुझे स्लाइडरटूल में माउस मूव फ़ंक्शन में टाइप कास्टिंग के साथ कोई समस्या है। यहां मेरी त्रुटि है: 'System.Windows.Input.MouseEventHandler' टाइप करने के लिए 'System.Windows.Input.MouseButtonEventHandler' प्रकार की ऑब्जेक्ट डालने में असमर्थ। इसे ठीक करने के तरीके पर कोई विचार? –

+1

इसके बारे में क्षमा करें। रूटेड इवेंट तकनीक के लिए मुझे MouseEventArgs की बजाय माउसबटन EventArgs में पास करने की आवश्यकता होती है क्योंकि MouseEventArgs वास्तव में इसके ईवेंट प्रकार की जांच करता है। मैंने आवश्यक परिवर्तन किया है और परिणामी कोड का परीक्षण किया है। ऐसा लगता है कि आप वही करना चाहते हैं जो आप चाहते हैं। का आनंद लें! –

0

कैसे

के बारे में
private void slider_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     Point point = e.GetPosition(slider); 
     slider.Value = point.X; 
    } 
5

बाद रे बर्न्स उत्तर प्रेरित होकर, सबसे आसान तरीका मैंने पाया यह है।
1. यदि आप क्लिक करें और स्लाइडर के बाहर माउस पकड़ और फिर स्लाइडर पर यह ले जाते हैं, खींचें शुरू कर देंगे:

इस समाधान (और इस विषय में सबसे अधिक अन्य) के साथ दो मुद्दों कर रहे हैं।
2. यदि आप स्लाइडर के ऑटोोटूलटिप का उपयोग कर रहे हैं, तो यह इस विधि के साथ खींचते समय काम नहीं करेगा।

mySlider.MouseMove += (sender, args) => 
{ 
    if (args.LeftButton == MouseButtonState.Pressed && this.clickedInSlider) 
    { 
     var thumb = (mySlider.Template.FindName("PART_Track", mySlider) as System.Windows.Controls.Primitives.Track).Thumb; 
     thumb.RaiseEvent(new MouseButtonEventArgs(args.MouseDevice, args.Timestamp, MouseButton.Left) 
     { 
      RoutedEvent = UIElement.MouseLeftButtonDownEvent, 
       Source = args.Source 
     }); 
    } 
}; 

mySlider.AddHandler(UIElement.PreviewMouseLeftButtonDownEvent, new RoutedEventHandler((sender, args) => 
{ 
    clickedInSlider = true; 
}), true); 

mySlider.AddHandler(UIElement.PreviewMouseLeftButtonUpEvent, new RoutedEventHandler((sender, args) => 
{ 
    clickedInSlider = false; 
}), true); 

clickedInSlider एक निजी सहायक चर कक्षा में somwhere परिभाषित किया गया है:

तो यहाँ एक उन्नत संस्करण है कि दोनों समस्याओं tackles है।

क्लिक किए गए इनस्लाइडर सहायक चर का उपयोग करके हम 1 से बचें। पूर्वावलोकनमोउसबटन डाउन इवेंट को संभाला जाता है (MoveToPoint = true के कारण), इसलिए हमें mySlider.AddHandler का उपयोग करना होगा।
स्लाइडर की बजाय थंब पर ईवेंट को बढ़ाकर, हम सुनिश्चित करते हैं कि ऑटोोटूलिप दिखाई देता है।

+0

बेहतर स्लाइडर के लिए अब तक का सबसे अच्छा संस्करण मिला है। मैं इसे अधिक स्पर्श अनुकूल स्लाइडर बनाने के लिए उपयोग करता हूं। हालांकि मुझे इसे उप-वर्ग में लागू करने के लिए क्लीनर मिला। धन्यवाद! – monoceres

0
  1. आपको कस्टम स्लाइडर और कस्टम अंगूठे की आवश्यकता है।जब आप स्लाइडर में क्लिक करें (अंगूठे में हिट नहीं) -

    var hitTestResult = VisualTreeHelper.HitTest(this, point); 
    if (hitTestResult == null) return; 
    var parent = hitTestResult.VisualHit.ParentOfType<Thumb>(); 
    if (parent != null) return; 
    _customThumb.OnMouseLeftButtonDown(e); 
    

आप कस्टम स्लाइडर विधि है, जो अंदर OnMouseLeftButtonDown(MouseButtonEventArgs e)

फोन में कॉल कर सकते हैं
  1. आप आप कर सकते हैं स्टैंडबार्ट थंब और OnMouseLeftButtonDown(MouseButtonEventArgs e)
1

पर कॉल करने के लिए रिफ्लेक्शन का उपयोग करें @ टिमपोहल्मन के उत्तर का बेहतर संस्करण यहां दिया गया है।

यह एक बार केवल MouseButtonEventHandler उठाता है। हालांकि अंगूठे प्रत्येक माउस चाल पर आंतरिक रूप से DragDeltaEventHandler उठाता है। लेकिन मुझे लगता है कि प्रत्येक माउस चाल पर अंगूठे पर MouseLeftButtonDownEvent आग लगाना अनावश्यक है।

इसके अलावा सहायक चर के लिए कोई आवश्यकता नहीं है।

इसे व्यवहार के रूप में लागू किया गया है। AssociatedObject वह स्लाइडर है जो इस व्यवहार से जुड़ा हुआ है।

XAML:

<Slider ...> 
    <i:Interaction.Behaviors> 
     <slid:FreeSlideBehavior /> 
    </i:Interaction.Behaviors> 
</Slider> 

व्यवहार:

public sealed class FreeSlideBehavior : Behavior<Slider> 
{ 
    private Thumb _thumb; 

    private Thumb Thumb 
    { 
     get 
     { 
      if (_thumb == null) 
      { 
       _thumb = ((Track)AssociatedObject.Template.FindName("PART_Track", AssociatedObject)).Thumb; 
      } 
      return _thumb; 
     } 
    } 

    protected override void OnAttached() 
    { 
     AssociatedObject.MouseMove += OnMouseMove; 
    } 

    protected override void OnDetaching() 
    { 
     AssociatedObject.MouseMove -= OnMouseMove; 
    } 

    private void OnMouseMove(object sender, MouseEventArgs args) 
    { 
     if (args.LeftButton == MouseButtonState.Released) return; 
     if(Thumb.IsDragging) return; 
     if (!Thumb.IsMouseOver) return; 

     Thumb.RaiseEvent(new MouseButtonEventArgs(args.MouseDevice, args.Timestamp, MouseButton.Left) 
     { 
      RoutedEvent = UIElement.MouseLeftButtonDownEvent 
     }); 
    } 
} 
+0

ध्यान दें कि आपको काम करने के लिए "इंटरएक्टिविटी" असेंबली जोड़ने की ज़रूरत है, जिसे डिफ़ॉल्ट रूप से शामिल नहीं किया गया है। –

+0

जाहिर है, व्यवहार का उपयोग करके डिजाइनर को तोड़ता है (https://connect.microsoft.com/VisualStudio/feedback/details/755407/xaml-designer-will-not-display-when-using-blend-sdk-behaviors, https: //catelproject.atlassian.net/browse/CTL-765)। मुझे लगता है कि मैं इससे बचूंगा ... –

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