拖动时如何停止滑块的更新值?

时间:2010-11-10 16:53:50

标签: wpf slider

我的滑块是它的值绑定到某个属性,并且属性一直在更新它。 在拖动[thumb on]滑块的同时,我想要阻止滑块的更新值进行绑定, 直到用户完成它的拖动。

Slider上是否有任何属性可以执行此操作,或者我需要为此编写代码?

提前致谢!

5 个答案:

答案 0 :(得分:5)

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

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

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

此滑块在拇指拖动完成之前不会更新该值。

另一个解决方案是截取Thumb上的ThumbDragDelta事件。如果你碰巧正在重新模仿Slider,这可能是一个更好的解决方案。例如,如果您已经编码了一个在给定的RoutedEvent上设置Handled true的EventBlocker类,您可以将它放在模板中:

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

但是对于大多数情况,你可能想要使用我的第一个解决方案。

答案 1 :(得分: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;
    }

}

答案 2 :(得分: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);
    }
}

答案 3 :(得分: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);
        }
    }
}

答案 4 :(得分:0)

这两个答案都没有对我有用 - 第一个不会滑动,第二个仍然在滑动期间更新了一个绑定值(这是问题所在 - 我认为)。 我最后对Slider进行了子类化,以包含第二个绑定值的依赖项属性(Value2,因为缺少更好的名称),在拖动Slider时不会更新。将反映所有其他值更新,并且一旦拖动完成,该值也会更新。 这个课程中可能存在一些漏洞,但它似乎在我的目的下工作正常。

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来代替普通的Slider,并绑定到Value2而不是Value(或者,实际上 - 绑定到两者,以便您可以在便宜到更新的字段中看到值更新,在开始昂贵的操作之前等待拖动完成。)

<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>

相关问题