编辑:在Slider.ValueChanged事件中长时间锁定。删除它可以阻止这种怪异。不好的做法,但这种行为对我来说仍然没有意义。它可能与消息队列有关,但如果可能的话,我想要一个解释。
当UI线程*上有重要工作时,WPF Slider不会按预期与鼠标交互。如果我沿一个方向拖动拇指,拇指通常会在鼠标光标前面前进,然后返回。该运动应该只导致增加ValueChanged事件,但事件有时会减少。有时这种振荡也发生在鼠标光标后面。似乎鼠标的位置是通过当前的速度来预测的。
我可以改变这种行为,还是我做错了什么?
切换IsSnapToTickEnabled无济于事。
*将大型BitmapSource分配给图像。 BitmapSource是在工作线程中创建的。
<Window x:Class="WPFSliderBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Name="image1" Stretch="Fill" />
<Slider HorizontalAlignment="Right" Name="slider1" VerticalAlignment="Stretch" Orientation="Vertical" />
</Grid>
</Window>
xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Threading;
namespace WPFSliderBug
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private volatile bool m_run = true;
private double m_sliderValue;
public MainWindow()
{
InitializeComponent();
this.Closing += new System.ComponentModel.CancelEventHandler(MainWindow_Closing);
this.slider1.Minimum = 1;
this.slider1.Maximum = 30;
this.slider1.SmallChange = 0.5;
this.slider1.LargeChange = 0.5;
this.slider1.TickFrequency = 0.5;
this.slider1.TickPlacement = System.Windows.Controls.Primitives.TickPlacement.Both;
this.slider1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(slider1_ValueChanged);
Thread t = new Thread((unused_state) =>
{
while (m_run)
{
BitmapSource bmp;
lock (this)
{
bmp = ToBitmapSource();
bmp.Freeze();
}
this.Dispatcher.Invoke(new Action(delegate()
{
image1.Source = bmp;
}));
}
});
t.Start();
}
void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lock (this)
{
m_sliderValue = e.NewValue;
}
}
void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
m_run = false;
}
public BitmapSource ToBitmapSource()
{
Random rng = new Random();
double dpi = 96;
int bytesPerPixel = 1;
int width = 2048;
int height = 2048;
int stride = ((width * 32 + 31) & ~31) / 8;
UInt32[] pixelData = new UInt32[width * height];
for (int i = 0; i < pixelData.Length; ++i)
{
double r = rng.NextDouble();
r = Math.Sin(r) * Math.Cos(r) + Math.Asin(r);
pixelData[i] = (uint)(r * UInt32.MaxValue);
}
BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi,
PixelFormats.Bgr32, null, pixelData, stride);
return bmpSource;
}
}
}