編集: Slider.ValueChanged イベントで長時間ロックがかかりました。これを削除すると、奇妙さが止まります。悪い習慣ですが、その動作はまだ私には意味がありません。おそらくメッセージキューが関係しているのでしょうが、できれば説明が欲しいです。
UI スレッド* に重要な作業がある場合、WPF スライダーは期待どおりにマウスと対話しません。親指を一方向にドラッグすると、親指がマウス カーソルの前に進み、その後戻ることがよくあります。移動によって ValueChanged イベントが増加するだけですが、イベントが減少することがあります。この振動は、マウス カーソルの背後でも発生することがあります。マウスの位置は、現在の速度によって予測されるようです。
この動作を変更できますか、それとも何か間違っていますか?
IsSnapToTickEnabled を切り替えても役に立ちません。
* 大きな BitmapSource を Image に割り当てる。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;
}
}
}