[英]WPF multi-level binding threading issue
just found an interesting WPF problem I could really use your help with: I've got a multi-level binding Binding="{Binding PreviewItem.Status}
which produces strange behavior if and only if the properties are updated from a background thread. I used diagnostics:PresentationTraceSources.TraceLevel=High
and what seems to happen is that if Status is updated, it prevents the binding from realizing the whole PreviewItem changes just a split second after it! 刚刚发现了一个有趣的WPF问题,我可以真正使用您的帮助:我有一个多级绑定
Binding="{Binding PreviewItem.Status}
,当且仅当从后台线程更新属性时,它才会产生奇怪的行为。使用的diagnostics:PresentationTraceSources.TraceLevel=High
,似乎发生的是,如果Status被更新,它会阻止绑定仅在其后一秒钟内实现整个PreviewItem的更改!
I managed to reproduce the behavior in an new, empty C# test project (VS 2012, .NET 4.5). 我设法在一个新的空C#测试项目(VS 2012,.NET 4.5)中重现该行为。 This is the main code: Both channel and TimelineItem are empty classes that just have a property with all the proper notifypropertychanged event notifications, StatusType is an Enum, the control's DataContext is set to
_channel
: 这是主要代码:channel和TimelineItem都是空类,只是具有带有所有正确notifypropertychanged事件通知的属性,StatusType是Enum,控件的DataContext设置为
_channel
:
Task.Run(() =>
{
if ( _channel.PreviewItem != null )
{
_channel.PreviewItem.Status = TimelineItem.StatusType.Default;
}
_channel.PreviewItem = new TimelineItem();
_channel.PreviewItem.Status = TimelineItem.StatusType.Preview;
});
}
Let's say we do this three times to create three items: 假设我们执行了三次以创建三个项目:
If I a) move the exact same code to the main thread or b) assign the new PreviewItem BEFORE changing the old items status, the code works! 如果我a)将完全相同的代码移至主线程,或b)在更改旧项目状态之前分配新的PreviewItem,则该代码有效! Unfortunately, I cannot use either approach in my project.
不幸的是,我不能在项目中使用任何一种方法。
Anyone got an idea why this does not work? 有人知道为什么这行不通吗? As far as I understood it, WPF is supposed to take care of dispatching the change event to the proper dispatcher.
据我了解,WPF应该负责将更改事件分派给适当的分派器。 Any help is highly appreciated...
任何帮助都受到高度赞赏...
Alex 亚历克斯
For some weird reason, the bug behavior only happens on Windows 7. Whole project can be found here . 出于某些奇怪的原因,该错误行为仅发生在Windows 7上。可以在此处找到整个项目。
The problems was resolved in a Hotfix: http://support.microsoft.com/kb/2783808/en-us 在修补程序中解决了这些问题: http : //support.microsoft.com/kb/2783808/en-us
In WPF, only the thread that created the UI (controls) may access\\modify that object. 在WPF中,只有创建UI(控件)的线程才能访问\\修改该对象。 For example, a background thread that is started from the main UI thread cannot update the contents of any control that was created on the UI thread.
例如,从主UI线程启动的后台线程无法更新在UI线程上创建的任何控件的内容。
You will need to invoke back onto the UI thread, there are multiple ways to do this, the following being one of the simplest: 您将需要重新调用UI线程,有多种方法可以执行此操作,以下是最简单的方法之一:
Application.Current.Dispatcher.Invoke(() =>
{
// your GUI related code here
});
Can you update your .Net version to 4.5.1/4.5.2 and recheck? 您可以将.Net版本更新为4.5.1 / 4.5.2并重新检查吗? This might be a bug which might have been fixed in a recent update.
这可能是一个错误,可能已在最近的更新中修复。 I checked your code on a Windows 7 machine only and was unable to reproduce it, so it is definitively framework version related.
我仅在Windows 7机器上检查了您的代码,但无法复制它,因此它绝对与框架版本相关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.