如何在拖动时停止更新滑块的值?
我滑动它的值绑定到一些属性,并且属性一直更新它。 拖动[thumb on]滑块时,我想要停止此绑定的更新值, ,直到用户完成拖动。如何在拖动时停止更新滑块的值?
滑块上有什么属性可以这么做,或者我需要为它编写代码?
在此先感谢!
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>
但你可能会想要去与我的第一个解决方案大多数情况下, 。
我有同样的问题,所以我做了一个简单的滑块扩展作为下一个最好的事情。再添两个事件在滑块:
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);
}
}
的答案都不为我工作 - 第一个也不会滑动,第二滑动时仍然更新绑定值(这是问题是什么 - 我认为)。 我结束了对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>
嗨该解决方案对我的作品。只需重写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;
}
}
我认为这个解决方案缺少的是(在我看来很重要)部分 - 如果由于视图模型值更改而更新了FinalValue,则Value不会更新,并且滑块的(视觉)状态不会反映视图模型上的值。换句话说 - 'FinalValue'只对'OneWayToSource'绑定模式有用。 – Grx70 2016-01-10 09:37:27
他可以为'FinalValue'添加一个'PropertyChangedCallback',并在那里更新'Value'。但功能仍然丢失。如果他在拇指旁边单击并在不拖动拇指的情况下更改值,会发生什么情况。 '价值'被更新,但'FinalValue'不会被更新。 – 2016-01-10 09:50:32
添加了一个标志来指示拖动,并且只有拖动滑块时才发送值更改事件。
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);
}
}
}
不起作用。 http://stackoverflow.com/questions/723502/wpf-slider-with-an-event-that-triggers-after-a-user-drags有一个解决方案 – Edza 2015-02-13 13:56:49
看来,OnThumbDragDelta无所事事呈现滑块无法操作(你不能滑动)。有趣的是,我认为这曾经工作得很好。 – tofutim 2011-04-18 17:09:43
我刚刚尝试了重写方法,并遇到与tofutim相同的问题。 – Septih 2011-09-22 14:31:25