Мое решение - это в основном решение Санто с несколькими флагами. Для меня ползунок обновляется либо из чтения потока, либо из-за манипуляций пользователя (либо путем перетаскивания мышью, либо с помощью клавиш со стрелками и т. Д.)
Сначала я написал код для обновления значения ползунка после чтения потока:
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()
}
}
Надеюсь, это кому-нибудь поможет!