1

假设我有一个命令的执行方法,如下所示:

    private void Execute()
    {
        // Bound to a wait indicator in the UI
        Searching = true;

        // Do some long running process
        Thread.Sleep(2000);

        Searching = false;
    }

当 Searching 设置为 True 时,它​​所绑定的 UI 元素将不会更新(即使 Searching 发送 OnPropertyChanged 调用)。

但是,一旦 Thread.Sleep 完成,UI 就会处理我的更改并显示 Searching 绑定到的等待指示器。

现在,我知道传统智慧是对长时间运行的进程(Thread.Sleep)的调用是异步的。

但是假设我没有使用异步库,有没有办法指示 WPF 现在对搜索执行绑定?

像这样的东西:

    private void Execute()
    {
        // Bound to a wait indicator in the UI
        Searching = true;

        // MADE UP CODE
        Binding.UpdateBindingNow("Searching");
        // END MADE UP CODE


        // Do some long running process
        Thread.Sleep(2000);

        Searching = false;
    }

更新:我尝试过的:

  • 使用 Dispatcher 尝试分别将命令发送到 UI。
  • 我还尝试了具有高优先级的调度程序。
4

2 回答 2

5

您需要将您的工作推入后台线程。在 UI 线程可以处理消息之前,绑定不会更新,这在您的操作完成之前不会发生。

异步是一种方法,但更经典的方法是仅用于BackgroundWorker执行此操作,所有版本的 WPF 都支持该方法。

如果您使用的是 .NET 4,您也可以通过 TPL 执行此操作:

private void Execute()
{
    // Bound to a wait indicator in the UI
    Searching = true;

    Task.Factory.StartNew( () => { 
        // Do long running work... 
    }).ContinueWith(t =>
    {
        // You can do work here, including touching UI controls/collections/etc
        Searching = false;
    }, TaskScheduler.FromCurrentSynchronizationContext());
}
于 2013-03-04T21:33:35.717 回答
1

我同意其他人的观点,将长时间运行的进程转移到后台/异步操作是最好的方法。既是因为您的 UI 不会为用户冻结,也因为您所做的任何事情(刷新绑定等)实际上都不会在长时间运行的进程工作时反映在 UI 中,因为 UI 线程将被阻塞。

也就是说,您的问题是您能否强制绑定从代码中评估/刷新,答案是肯定的。您可以通过调用以下代码来完成UpdateTarget此操作BindingExpression

labelTextBlock.GetBindingExpression(TextBlock.TextProperty).UpdateTarget();

还有一种UpdateSource方法BindingExpression可以以几乎相同的方式使用,只影响源而不是目标。

同样,如果您的 UI 线程被阻塞,它可能无法完成您所希望的,但这就是您将强制绑定重新评估的方式。

于 2013-03-04T21:42:07.137 回答