C# WPF绑定未从Dispatchermer更新

C# WPF绑定未从Dispatchermer更新,c#,wpf,data-binding,C#,Wpf,Data Binding,下面是我遇到的一个问题的简化版本。这是一个相当普遍的问题,但我正在努力找到解决办法 我有一个实例化的类,它绑定到主窗口上的一个项。此类包含用于更新值的Dispatcher。在给定的示例中,它每秒递增该值1 我希望表单上的绑定项通过相应地更新其值来反映此更改,但它从不更新 通过阅读StackOverflow上类似问题的其他回复,我感觉这是由于主UI线程与导致增量的线程分开运行的性质造成的 我的头撞在墙上,尽管我试图让这个绑定随着我的调度员的每次呼叫而更新 以下是我希望每秒更新的表单元素: <

下面是我遇到的一个问题的简化版本。这是一个相当普遍的问题,但我正在努力找到解决办法

我有一个实例化的类,它绑定到主窗口上的一个项。此类包含用于更新值的Dispatcher。在给定的示例中,它每秒递增该值1

我希望表单上的绑定项通过相应地更新其值来反映此更改,但它从不更新

通过阅读StackOverflow上类似问题的其他回复,我感觉这是由于主UI线程与导致增量的线程分开运行的性质造成的

我的头撞在墙上,尽管我试图让这个绑定随着我的调度员的每次呼叫而更新

以下是我希望每秒更新的表单元素:

<TextBox Text="{Binding val}" Width="100"/>
最后,这是我创建的类。创建时,它配置一个计时器,用于每秒更新一个值。每次更新此值时,我都希望主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)); } } 类BasicTimer:INotifyPropertyChanged { 调度定时器; uint _val=10; 公共uint val { 得到 { 返回值; } 设置 { 如果(_val!=值) { _val=值; 不动产变更(“价值”); } } } 公共基本分子() { _计时器=新调度程序(); _timer.Tick+=neweventhandler(TimerTick); _timer.Interval=新的时间跨度(0,0,1); _timer.Start(); } 私有void TimerTick(对象发送方、事件参数) { val++; 控制台写入线(val); } 公共事件属性更改事件处理程序属性更改; 受保护的无效OnPropertyChanged(字符串PropertyName) { if(PropertyChanged!=null) { PropertyChanged(这是新的PropertyChangedEventArgs(PropertyName)); } } 我想我已经设法避免了忘记INotifyPropertChanged的常见陷阱,其他模型中的其他绑定值也可以正常工作。我遇到问题的只是通过线程更新的这个属性。我还尝试使用简单的计时器创建类似的计时器,但我遇到了同样的问题


如果您有任何想法,我们将不胜感激,谢谢!

我相信您的问题在于呼叫
OnPropertyChanged

uint _val = 10;
public uint val
{
  get
  {
    return _val;
  }
  set
  {
    if(_val!=value)
    {
      _val = value;
      OnPropertyChanged("Value");
    }
  }
}
那应该是

OnPropertyChanged("val");
调用
OnPropertyChanged
时的字符串必须与属性名称匹配

编辑

您希望传递给
OnPropertyChanged
的名称始终与属性名称匹配的原因是,数据绑定订阅对象的
PropertyChanged
事件,并在传递给其事件处理程序的参数中监视该字符串中的值。如果传递的名称与名称不匹配,则为look对于,它将忽略通知。它仅在名称匹配时更新绑定到该属性的控件的值

正如Aron在评论中提到的,您可以在
OnPropertyChanged
方法中使用
CallerMemberAttribute
,以确保始终正确地将属性名称传递给该方法。根据的答案,您的方法如下所示:

protected void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
  if (PropertyChanged != null)
  {
    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
  }
}
然后,您可以从属性的setter调用它,而不使用任何参数,并且名称始终是正确的


正如链接问题的答案所说,这段代码编译成IL代码,该代码与您在调用中硬编码字符串时生成的代码相同,因此这一技巧将始终有效,速度也一样快。

此外,他不应该从调度方法更新属性吗?在WPF中,用户不能从U以外的其他位置进行任何UI交互IThreadWPF对
INotifyPropertyChanged
接口的支持允许它处理来自另一个线程的对象的更新。虽然我对细节不太熟悉,但我相信WPF会收到通知,并在UI线程的
Dispatcher
上调度代码以处理事件。因为OP的类但是,如果对象是在UI线程上实例化的,
DispatchTimer
,则无论如何,
DispatchTimer
将在UI线程上运行。@TonyVitabile我建议添加一点关于使用
CallerMemberNameAttribute
,以及为什么希望
OnPropertyChanged
调用与属性名称完全匹配的内容@TonyVitabile已检查,您是正确的。将OnPropertyChanged的参数设置为“val”使一切顺利进行。谢谢您的时间!
protected void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
  if (PropertyChanged != null)
  {
    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
  }
}