2010-11-10 76 views
10

我滑动它的值绑定到一些属性,并且属性一直更新它。 拖动[thumb on]滑块时,我想要停止此绑定的更新值, ,直到用户完成拖动。如何在拖动时停止更新滑块的值?

滑块上有什么属性可以这么做,或者我需要为它编写代码?

在此先感谢!

回答

5

Slider的模板包含一个Thumb,当鼠标移动时引发ThumbDragDelta事件。当接收到ThumbDragDelta事件时,滑块总是立即更新绑定值。

诀窍是停止此事件。最简单的方法是子类滑块:

public class SliderIgnoreDelta : Slider 
{ 
    protected override void OnThumbDragDelta(DragDeltaEventArgs e) 
    { 
    // Do nothing 
    } 
} 

此滑块不会更新值,直到拇指拖动完成。

另一种解决方案是截取Thumb上的ThumbDragDelta事件。无论如何,如果你碰巧重新模拟Slider,这可能是更好的解决方案。例如,如果你已经有了一个EventBlocker类编写了该组给定的RoutedEvent处理好真实的,你可以把这个在您的模板:

<Track.Thumb> 
    <Thumb my:EventBlocker.EventToBlock="{x:Static Thumb.DragDeltaEvent}" /> 
</Track.Thumb> 

但你可能会想要去与我的第一个解决方案大多数情况下, 。

+2

看来,OnThumbDragDelta无所事事呈现滑块无法操作(你不能滑动)。有趣的是,我认为这曾经工作得很好。 – tofutim 2011-04-18 17:09:43

+2

我刚刚尝试了重写方法,并遇到与tofutim相同的问题。 – Septih 2011-09-22 14:31:25

2

我有同样的问题,所以我做了一个简单的滑块扩展作为下一个最好的事情。再添两个事件在滑块:

ThumbDragStarted ThumbDragCompleted

public class SliderWithDraggingEvents : Slider 
{ 
    public delegate void ThumbDragStartedHandler(object sender, DragStartedEventArgs e); 
    public event ThumbDragStartedHandler ThumbDragStarted; 


    public delegate void ThumbDragCompletedHandler(object sender, DragCompletedEventArgs e); 
    public event ThumbDragCompletedHandler ThumbDragCompleted; 

    protected override void OnThumbDragStarted(DragStartedEventArgs e) 
    { 
     if (ThumbDragStarted != null) ThumbDragStarted(this, e); 
     base.OnThumbDragStarted(e); 
    } 

    protected override void OnThumbDragCompleted(DragCompletedEventArgs e) 
    { 
     if (ThumbDragCompleted != null) ThumbDragCompleted(this, e); 
     base.OnThumbDragCompleted(e); 
    } 
} 
0

的答案都不为我工作 - 第一个也不会滑动,第二滑动时仍然更新绑定值(这是问题是什么 - 我认为)。 我结束了对Slider进行子分类以包含第二个绑定值(值为2,因为想要更好的名称)的依赖项属性,该属性在拖动滑块时未得到更新。所有其他值更新都会反映出来,并且该值在拖动完成后也会更新。 这个班可能有一些漏洞,但它似乎对我的目的工作正常。

public class SliderNoDragUpdates : Slider 
{ 
    public static readonly DependencyProperty Value2Property = 
     DependencyProperty.RegisterAttached(
      "Value2", 
      typeof(double), 
      typeof(SliderNoDragUpdates), 
      new FrameworkPropertyMetadata(0D, new PropertyChangedCallback(OnValue2Changed), new CoerceValueCallback(CoerceValue2)) 
      { 
       BindsTwoWayByDefault = true, 
      }); 

    private static object CoerceValue2(DependencyObject d, object value) 
    { 
     SliderNoDragUpdates c = (SliderNoDragUpdates)d; 
     double v = (double)value; 
     if (v < c.Minimum) v = c.Minimum; 
     if (v > c.Maximum) v = c.Maximum; 
     return v; 
    } 

    private static void OnValue2Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     d.CoerceValue(Value2Property); 
    } 

    public double Value2 
    { 
     get { return (double)this.GetValue(Value2Property); } 
     set 
     { 
      if (value != Value2) 
       this.SetValue(Value2Property, value); 
      if (value != Value) 
       this.SetValue(ValueProperty, value); 
     } 
    } 

    private bool _dragging = false; 

    protected override void OnThumbDragStarted(System.Windows.Controls.Primitives.DragStartedEventArgs e) 
    { 
     _dragging = true; 

     base.OnThumbDragStarted(e); 
    } 

    protected override void OnThumbDragCompleted(System.Windows.Controls.Primitives.DragCompletedEventArgs e) 
    { 
     _dragging = false; 
     Value2 = Value; 

     base.OnThumbDragCompleted(e); 
    } 

    protected override void OnValueChanged(double oldValue, double newValue) 
    { 
     if (!_dragging) 
      Value2 = Value; 

     base.OnValueChanged(oldValue, newValue); 
    } 
} 

要使用它,实例化一个SliderNoDragUpdates代替正常的滑块,并绑定到值2,而不是价值(或者更确切地说 - 绑定到两个,这样就可以在一个便宜的,看值更新更新字段,同时在开始昂贵的操作之前等待拖动完成)。

<Window x:Class="slidertest.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:slidertest" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="40"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <local:SliderNoDragUpdates Value="{Binding slider_value}" Value2="{Binding slider_value2}" Minimum="0" Maximum="100" VerticalAlignment="Center"/> 
    <Viewbox Grid.Row="1"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBox FontWeight="Bold" FontFamily="Arial" FontSize="25" Text="{Binding slider_value}"/> 
      <TextBox FontWeight="Bold" FontFamily="Arial" FontSize="25" Text="{Binding slider_value2}"/> 
     </StackPanel> 
    </Viewbox> 
</Grid> 

3

嗨该解决方案对我的作品。只需重写Slider类并将其绑定到xaml中的FinalValue即可。

public class ExSlider : Slider 
{ 
    public double FinalValue 
    { 
     get { return (double)GetValue(FinalValueProperty); } 
     set { SetValue(FinalValueProperty, value); } 
    } 

    public static readonly DependencyProperty FinalValueProperty = 
     DependencyProperty.Register(
      "FinalValue", typeof(double), typeof(ExSlider), 
      new FrameworkPropertyMetadata(0d, 
       FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 

    protected override void OnThumbDragCompleted(DragCompletedEventArgs e) 
    { 
     base.OnThumbDragCompleted(e); 
     FinalValue = Value; 
    } 

} 
+1

我认为这个解决方案缺少的是(在我看来很重要)部分 - 如果由于视图模型值更改而更新了FinalValue,则Value不会更新,并且滑块的(视觉)状态不会反映视图模型上的值。换句话说 - 'FinalValue'只对'OneWayToSource'绑定模式有用。 – Grx70 2016-01-10 09:37:27

+1

他可以为'FinalValue'添加一个'PropertyChangedCallback',并在那里更新'Value'。但功能仍然丢失。如果他在拇指旁边单击并在不拖动拇指的情况下更改值,会发生什么情况。 '价值'被更新,但'FinalValue'不会被更新。 – 2016-01-10 09:50:32

1

添加了一个标志来指示拖动,并且只有拖动滑块时才发送值更改事件。

public class CustomSlider:Slider 
{ 

    public bool IsDragging { get; protected set; } 
    protected override void OnThumbDragCompleted(System.Windows.Controls.Primitives.DragCompletedEventArgs e) 
    { 
     IsDragging = false; 
     base.OnThumbDragCompleted(e); 

    } 

    protected override void OnThumbDragStarted(System.Windows.Controls.Primitives.DragStartedEventArgs e) 
    { 
     IsDragging = true; 
     base.OnThumbDragStarted(e); 
    } 

    protected override void OnValueChanged(double oldValue, double newValue) 
    { 
     if (!IsDragging) 
     { 
      base.OnValueChanged(oldValue, newValue); 
     } 
    } 
} 
+0

不起作用。 http://stackoverflow.com/questions/723502/wpf-slider-with-an-event-that-triggers-after-a-user-drags有一个解决方案 – Edza 2015-02-13 13:56:49