以下是我遇到的问题的简化版本。这是一个相当普遍的问题,但我很难找到解决方案。
我已经将一个实例化的类绑定到主窗口上的某个项目。此类包含DispatcherTimer,用于更新值。在给出的示例中,它每秒将此值递增1。
我希望我的表单上的绑定项通过相应地更新其值来反映此更改,但它永远不会更新。
从阅读StackOverflow上类似问题的其他回答我感觉这是由于主要UI线程的性质分别运行到导致增量的线程。
我试图通过每次调用我的DispatcherTimer来更新此绑定时,我的头撞在墙上。
以下是我想要每秒更新的表单元素:
<TextBox Text="{Binding val}" Width="100"/>
接下来,这是包含计时器和我的应用程序配置的类的实例化:
BasicTimer basictimer;
public MainWindow()
{
InitializeComponent();
basictimer = new BasicTimer();
DataContext = basictimer;
}
最后,这是我创建的课程。创建时,它会配置一个计时器,用于每秒更新一次值。每次更新此值时,我都希望主UI被通知更改并相应地更新。但是,这条消息似乎没有通过。
class BasicTimer: INotifyPropertyChanged { DispatcherTimer _timer; uint _val = 10; public uint val { get { return _val; } set { if(_val!=value) { _val = value; OnPropertyChanged("Value"); } } } public BasicTimer() { _timer = new DispatcherTimer(); _timer.Tick += new EventHandler(TimerTick); _timer.Interval = new TimeSpan(0, 0, 1); _timer.Start(); } private void TimerTick(object sender, EventArgs e) { val++; Console.WriteLine(val); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string PropertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); } }
我认为我已经设法避免了忘记INotifyPropertChanged的常见陷阱,其他模型的其他绑定值工作得很好。只是这个属性正在通过我遇到问题的主题进行更新。我也尝试使用简单的计时器创建一个类似的计时器,但我遇到了同样的问题。
非常感谢任何想法,谢谢!
答案 0 :(得分:2)
我认为您的问题出在OnPropertyChanged
的调用中:
uint _val = 10;
public uint val
{
get
{
return _val;
}
set
{
if(_val!=value)
{
_val = value;
OnPropertyChanged("Value");
}
}
}
那应该是
OnPropertyChanged("val");
OnPropertyChanged
调用中的字符串必须与属性名称匹配。
修改强>
您希望传递给OnPropertyChanged
的名称始终与属性名称匹配的原因是因为数据绑定订阅了对象的PropertyChanged
事件,并且正在监视该字符串中的值参数传递给它的事件处理程序。如果传递的名称与其查找的名称不匹配,则会忽略该通知。它仅在名称匹配时更新绑定到该属性的控件的值。
正如Aron在评论中提到的,您可以使用CallerMemberAttribute
方法中的OnPropertyChanged
来确保属性名称始终正确传递给方法。根据{{3}}的答案,您的方法如下所示:
protected void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
然后,您将使用属性的setter中没有参数来调用它,并且名称将始终正确。
正如链接问题的答案所说,此代码编译成IL代码,与您在调用中对字符串进行硬编码时产生的代码相同,因此这个技巧将始终有效并且速度也一样快。