如何强制使用忙碌指示器?

3

我使用了扩展 WPF 工具包中的 BusyIndicator

我的 XAML 代码:

<extToolkit:BusyIndicator Name="wait" IsBusy="False" Cursor="Wait" Grid.ColumnSpan="3" Margin="10,10,10,10"/>

我的代码:

private void esp_Click(object sender, RoutedEventArgs e)
{
    wait.IsBusy = true;

    // My work here make some time to finish

    wait.IsBusy = false;
}

但是它从未被显示出来。我尝试在函数结尾处使用MessageBox,但BusyIndicator在MessageBox之后仍然没有被显示。
我尝试过:
wait.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                       (Action)delegate
{
    wait.IsBusy = true;
});

但是我什么也没有得到!!!问题出在哪里,我无法解决它?

我找到了一个类似的问题,但我的问题不同,指示器出现在函数完成后。

2个回答

6
问题在于您正在调度程序的线程中执行所有工作(我假设esp_Click是一个事件处理程序)。这意味着在执行长时间任务时,UI不会得到更新。
您需要在单独的线程中执行工作-可以创建一个新线程、使用线程池或创建一个任务。在开始工作之前将IsBusy设置为true,在完成工作后将其设置为false。当从另一个线程更新wait.IsBusy时,您需要使用Dispatcher.BeginInvoke/Invoke
示例代码:
private void LongRunningTask() 
{
   // your long running code

   // after you complete:
   Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                           (Action)delegate
    {
        wait.IsBusy = false;
    }); 
}

private void esp_Click(object sender, RoutedEventArgs e)
{
   wait.IsBusy = true; // either here, or in your long running task - but then remember to use dispatcher

   var thread = new Thread(LongRunningTask);
   thread.Start();

   // OR

   ThreadPool.QueueUserWorkItem(state => LongRunningState());

   // OR, in .NET 4.0

   Task.Factory.StartNew(LongRunningTask);
}

请注意,这些解决方案都不处理异常 - 您需要自己添加错误处理(或在最后一个示例中使用任务继续)。

我何时需要在我的长代码之前添加 wait.IsBusy = true; ? - Akrem
我在我的代码中使用了一些文本框,并且对于该文本框出现了异常“不同的线程拥有它”!! - Akrem
每当您从除了调度程序的其他线程访问任何UI元素时,必须使用调度程序 - 文本框、繁忙指示器、按钮等等。 - maciejkow
Silverlight 4 中应该做什么?我不能强制它刷新吗?我真的没有执行与界面隔离的任何处理。:( - Jordan

2
你可以使用INotifyPropertyChanged实现这个功能:
<extToolkit:BusyIndicator Name="wait" IsBusy="{Binding IsBusy}" Cursor="Wait" Grid.ColumnSpan="3" Margin="10,10,10,10"/>

还有 C#:

    /// <summary>
    /// The <see cref="IsBusy" /> property's name.
    /// </summary>
    public const string IsBusyPropertyName = "IsBusy";
    private bool _isBusy = false;

    public bool IsBusy
    {
        get
        {
            return _isBusy;
        }

        set
        {
            if (_isBusy != value)
            {
                _isBusy = value;
                RaisePropertyChanged(IsBusyPropertyName);                   
            }
        }
    }

谢谢你指出了显而易见的问题。说真的,我一直在想为什么我的BusyIndicator没有显示出来,浪费了半个小时。 - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接