在InitializeComponents之后的我的Window构造函数中,我需要创建一个对象并将其绑定到datagrid。由于对象创建花费了太多时间,因此窗口需要一段时间才能显示出来。所以我决定将对象的创建移动到后台线程,并通过执行dispatcher.invoke来“委托回”到UI线程来执行绑定。但这失败了。
奇怪的是,如果我尝试在Dispatcher.invoke中设置一个矩形的可见性,那可行,但DataGrid.setbinding不行!有任何想法吗?我已经尝试了与后台工作程序和threadstart相同的东西,但我一直得到同样的错误。我无法访问DataGrid对象,即使它发生在调度程序内部调用委托。在我理解这是如何工作的时候,我肯定会遗漏一些东西。任何建议将不胜感激。谢谢!
StartupDelegate s = new StartupDelegate(CreateModel);
s.BeginInvoke(delegate(IAsyncResult aysncResult) { s.EndInvoke(aysncResult); }, null);
internal CreateModel()
{
Model d = new Model();
Dispatcher.Invoke( DispatcherPriority.Normal,
new Action<Model>(
delegate(Model d1)
{
mModel = d1; // mModel is a property defined in Window
Binding b = new Binding();
b.Source = mModel;
MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); // << dies here with - The calling thread cannot access this object because a different thread owns it.
}
}
更新: 使用只运行一次的调度程序结束。将绑定代码放入其Tick委托中。但我仍然很好奇为什么上面的代码没有。
答案 0 :(得分:0)
我建议另辟蹊径。
不应该从代码中调用绑定,而应该在XAML中定义它。
您可以在窗口上再添加一个Model类型的DependencyProperty,并将其命名为“CurrentModel”并将其初始值设置为NULL。看起来你已经有一个名为mModel的属性,是DependencyProperty?
您可以定义CurrentModel到DataGrid的绑定或XAML中的哪个控件。
在委托结束时,Dispatcher.Invoke应该只设置CurrentModel,绑定将自动完成。
答案 1 :(得分:0)
您在调用Invoke
的调度程序实例?
我猜测它是正在执行CreateModel
的后台线程的Dispatcher,而不是来自UI线程的Dispatcher。
DataGrid是一个控件,因此派生自DispatcherObject
。每个这样的对象通过其Dispatcher
属性公开其所有者线程的调度程序,这是您应该用来调用控件上的方法的属性。
更改呼叫中的调度程序应该有效:
internal CreateModel()
{
Model d = new Model();
// Invoke the action on the dispatcher of the DataGrid
MainDataGrid.Dispatcher.Invoke( DispatcherPriority.Normal,
new Action<Model>(
delegate(Model d1)
{
mModel = d1; // mModel is a property defined in Window
Binding b = new Binding();
b.Source = mModel;
MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb);
}
}
您还可以在执行后台操作之前将UI线程的Dispatcher存储在字段中,但是使用控件的Dispatcher可以更好地显示代码的意图:“我想在此控件所属的任何线程上调用它”
更新:我刚刚意识到这是您控件的实例方法,因此您使用的调度程序实例是正确的。非常适合在深夜回答。此外,您的代码适用于我,用IEnumerable替换您的模型。您的模型中有什么特别的东西吗?