告诉WPF评估绑定

时间:2013-03-04 21:29:51

标签: c# .net wpf binding

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

    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处理我的更改并显示搜索绑定的等待指示符。

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

但是假设我没有使用Async库,有没有办法指示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。
  • 我还尝试了优先级高的Dispatcher。

2 个答案:

答案 0 :(得分:5)

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

Async是一种方法,但更经典的方法是使用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());
}

答案 1 :(得分:1)

我同意其他人的说法,将长时间运行的流程转移到后台/异步操作是最好的方法。两者都是因为你的UI不会为用户冻结,也因为无论你做什么(刷新你的绑定,无论如何)都不会实际反映在UI中,而长时间运行的进程正在工作,因为UI线程将被阻止。 / p>

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

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

UpdateSource上还有一个BindingExpression方法可以大致相同的方式使用,只影响来源而非目标。

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