私の解決策は基本的にSantoの解決策であり、さらにいくつかのフラグがあります。私の場合、スライダーは、ストリームの読み取りまたはユーザー操作(マウスのドラッグまたは矢印キーの使用など)のいずれかから更新されています。
最初に、ストリームの読み取りからスライダー値を更新するコードを記述しました。
delegate void UpdateSliderPositionDelegate();
void UpdateSliderPosition()
{
if (Thread.CurrentThread != Dispatcher.Thread)
{
UpdateSliderPositionDelegate function = new UpdateSliderPositionDelegate(UpdateSliderPosition);
Dispatcher.Invoke(function, new object[] { });
}
else
{
double percentage = 0; //calculate percentage
percentage *= 100;
slider.Value = percentage; //this triggers the slider.ValueChanged event
}
}
次に、ユーザーがマウスドラッグでスライダーを操作しているときにキャプチャしたコードを追加しました。
<Slider Name="slider"
Maximum="100" TickFrequency="10"
ValueChanged="slider_ValueChanged"
Thumb.DragStarted="slider_DragStarted"
Thumb.DragCompleted="slider_DragCompleted">
</Slider>
そして、背後にコードを追加しました:
/// <summary>
/// True when the user is dragging the slider with the mouse
/// </summary>
bool sliderThumbDragging = false;
private void slider_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
sliderThumbDragging = true;
}
private void slider_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
sliderThumbDragging = false;
}
ユーザーがマウスドラッグでスライダーの値を更新しても、ストリームが読み取られて呼び出されるため、値は変更されますUpdateSliderPosition()
。競合を防ぐために、UpdateSliderPosition()
変更する必要がありました:
delegate void UpdateSliderPositionDelegate();
void UpdateSliderPosition()
{
if (Thread.CurrentThread != Dispatcher.Thread)
{
UpdateSliderPositionDelegate function = new UpdateSliderPositionDelegate(UpdateSliderPosition);
Dispatcher.Invoke(function, new object[] { });
}
else
{
if (sliderThumbDragging == false) //ensure user isn't updating the slider
{
double percentage = 0; //calculate percentage
percentage *= 100;
slider.Value = percentage; //this triggers the slider.ValueChanged event
}
}
}
これにより競合を防ぐことができますが、値がユーザーによって更新されているのか、への呼び出しによって更新されているのかを判断することはできませんUpdateSliderPosition()
。これは、今度は内から設定されるさらに別のフラグによって修正されますUpdateSliderPosition()
。
/// <summary>
/// A value of true indicates that the slider value is being updated due to the stream being read (not by user manipulation).
/// </summary>
bool updatingSliderPosition = false;
delegate void UpdateSliderPositionDelegate();
void UpdateSliderPosition()
{
if (Thread.CurrentThread != Dispatcher.Thread)
{
UpdateSliderPositionDelegate function = new UpdateSliderPositionDelegate(UpdateSliderPosition);
Dispatcher.Invoke(function, new object[] { });
}
else
{
if (sliderThumbDragging == false) //ensure user isn't updating the slider
{
updatingSliderPosition = true;
double percentage = 0; //calculate percentage
percentage *= 100;
slider.Value = percentage; //this triggers the slider.ValueChanged event
updatingSliderPosition = false;
}
}
}
最後に、スライダーがユーザーによって更新されているのか、次の呼び出しによって更新されているのかを検出できますUpdateSliderPosition()
。
private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (updatingSliderPosition == false)
{
//user is manipulating the slider value (either by keyboard or mouse)
}
else
{
//slider value is being updated by a call to UpdateSliderPosition()
}
}
それが誰かを助けることを願っています!