我的DependencyProperty存在问题。假设您有一个更新某些UI元素的计时器,如果每100ms调用一次回调,这反过来更新UI然后我没有问题,但是,如果计时器设置为~10ms,例如,一些调用将获得忽略。我做了一个小解决方案来重现问题:
这是一个带有依赖属性的自定义UIElement:
public class CustomLabel : Label
{
public float Range
{
get { return (float)GetValue(MaxRangeProperty); }
set { SetValue(MaxRangeProperty, value); }
}
public static readonly DependencyProperty MaxRangeProperty =
DependencyProperty.Register("Range", typeof(float), typeof(CustomLabel),
new PropertyMetadata(0f, RangePropertyChanged));
private static void RangePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var self = d as CustomLabel;
Debug.WriteLine("CustomLabel");
self.Content = self.Range;
}
}
这是一个ViewModel,它触发一个计时器并更新一个属性,而该属性又应该调用CustomLabel上DependencyProperty上的CallBack。
public class ViewModel : INotifyPropertyChanged
{
Timer timer;
Thread t;
public ViewModel()
{
t = new Thread(() => timer = new Timer(new TimerCallback(CallBack), null, 0, 10));
t.Start();
Range = 100;
}
void CallBack(object state)
{
Range = (new Random()).Next(0, 1000);
}
private float _range;
public float Range
{
get { return _range; }
set
{
if (_range != value)
{
_range = value;
NotifyPropertyChanged();
Debug.WriteLine("ViewModel");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
这是CustomLabel所在的View和ViewModel:
<Window x:Class="TimerTest.MainWindow"
xmlns:local="clr-namespace:TimerTest"
Title="MainWindow">
<Grid>
<local:CustomLabel x:Name="customLabel" Range="{Binding Range}"/>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ViewModel = new ViewModel();
customLabel.DataContext = ViewModel;
}
public ViewModel ViewModel { get; set; }
}
所以,我在DependencyProperty的每一侧都做了一些Debug.WriteLine()
语句,输出如下:
100ms 10ms
CustomLabel ViewModel
ViewModel CustomLabel
CustomLabel ViewModel
ViewModel ViewModel
CustomLabel CustomLabel
ViewModel ViewModel
CustomLabel ViewModel
ViewModel ViewModel
CustomLabel ViewModel
ViewModel CustomLabel
为什么会发生这种情况,我该怎么办呢? 谢谢你的时间。
答案 0 :(得分:1)
NotifyPropertyChanged
事件由使用队列的Dispatcher
处理。调度程序正在以比它们添加到队列中更慢的速率处理事件。
使用DispatcherTimer
可能会让您更快地更新:
DispatcherTimer timer =
new DispatcherTimer(TimeSpan.FromMilliseconds(10),
DispatcherPriority.Normal,
delegate
{
MyCustomLabel.SetValue(MaxRangeProperty, viewModel.Range);
},
Dispatcher);
也...
默认情况下,您使用的System.Threading.Timer类的精度不能达到10毫秒。它将使用操作系统计时器。
引用有关计时器分辨率的Microsoft文档:
Windows 7上的默认计时器分辨率为15.6毫秒(ms)
可以通过调用Windows API来提高计时器分辨率,但这可能会导致电池耗尽。