2

在 InitializeComponents 之后的 Window 构造函数中,我需要创建一个对象并将其绑定到数据网格。由于创建对象花费了太多时间,因此窗口需要一段时间才能显示出来。所以我决定将对象的创建移到后台线程,并通过执行 dispatcher.invoke 来“委托”到 UI 线程来执行绑定。但这失败了。

奇怪的是,如果我尝试设置我在 Dispatcher.invoke 中的矩形的可见性,它可以工作,但 DataGrid.setbinding 不行!有任何想法吗?我在后台工作人员和线程启动中尝试过同样的事情,但我一直收到同样的错误。我无法访问 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 委托中是可行的。但我仍然很好奇为什么上面的代码没有。

4

2 回答 2

0

我会建议另一种方式。

不应从代码调用绑定,而应在 XAML 中定义它。

您可以在窗口上再添加一个 Model 类型的 DependencyProperty,并将其命名为“CurrentModel”,并将其初始值设置为 NULL。看起来您已经有一个名为 mModel 的属性,是 DependencyProperty 吗?

您可以将 CurrentModel 绑定到 DataGrid 或 XAML 中的任何控件。

在您的委托结束时,Dispatcher.Invoke 应该只设置 CurrentModel,绑定将自动完成。

于 2009-07-25T12:48:14.623 回答
0

您在哪个调度程序实例上调用Invoke

我猜这是正在执行的后台线程中的调度程序CreateModel,而不是来自 UI 线程的调度程序。

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。你的模型有什么特别之处吗?

于 2011-08-10T21:17:40.083 回答