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