C#WPF - 长按操作按钮单击

时间:2015-07-19 17:43:58

标签: c# .net wpf user-interface asynchronous

我有Button,它会在点击时调用另一种方法。 另一种方法执行的操作可能需要很长时间...... 所以我想创建一个Label,它出现在操作开始并告诉用户等待,操作完成后,Label将消失。唯一的问题是,因为Button是一个UI元素(我认为原因是这样),所以仅在Label点击内更改Button的调用Button点击完成后激活...(所以基本上Label在点击之前是不可见的,并且在此期间无法更改,因此它保持这种状态。)

这是我的代码:

private void SearchButtonActions()
{
        UI.InvokeA(() => lstFiles.ItemsSource = FDItems);
        bool SearchAndListing = false;
        //UI.InvokeA(() => lblWait.Height = double.NaN);
        //UI.InvokeA(() => lblWait.Visibility = Visibility.Visible);
        //UI.InvokeA(() => lblWait.Content = "Search Started...");
        int index = cbTypes.SelectedIndex;
        string selecteditem = cbSearchOption.SelectedItem.ToString();
        SearchAndListing = FD.Search(index, selecteditem);
        FDItems = new ObservableCollection<Item>(FD.Items);
        //UI.InvokeA(() => lblWait.Height = 0);
        //UI.InvokeA(() => lblWait.Visibility = Visibility.Hidden);
        //UI.InvokeA(() => lblWait.Content = "Search Ended.");
        if (SearchAndListing)
        {
            UI.InvokeA(() => lstFiles.ItemsSource = FDItems);
            UI.InvokeA(() => lblCount.Content = string.Format("Items: {0}", FDItems.Count));
        }
}

我在谈论改变lblWait的方法...... btw:UI.Invoke - 是Dispatcher.Current.InvokeAsync(Action)

的快捷方式

我已尝试使用TasksBackGroundWorker,并将UI.Invoke更改为Invokesynchronically而不是asynchronically),以及所有没有成功......

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

之前我遇到过这个问题,直到现在才开始考虑它。

你的论点是正确的,UI线程当前正在运行Click方法,所以它很忙,不会运行任何其他东西。

即使使用调度程序,它仍然执行click方法,因此ui线程会弹出下一个委托,只有在完成后才会运行。

所以这不起作用:

   lbl.Visibility = Visibility.Visible;
   Thread.Sleep(3000);

这不起作用:

    Dispatcher.Invoke(() => lbl.Visibility = Visibility.Visible);
    Dispatcher.Invoke(() => Thread.Sleep(3000));

从后台线程调度ui操作会起作用。

XAML:

    <StackPanel>   
       <Button Click="Button_Click" Content="Click"/>
       <Label x:Name="lbl" Content="Label" Visibility="Hidden" Foreground="Red" FontSize="22" HorizontalAlignment="Center"/>
     </StackPanel>

CS:

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        await Dispatcher.InvokeAsync(() => 
        {
            Debug.WriteLine("Visibility");
            lbl.Visibility = Visibility.Visible;                
        });

        await Task.Run(() =>
        {
            return Dispatcher.InvokeAsync(() => Thread.Sleep(3000));
        });            
    }

仅供参考:您可能想知道我为什么不使用调度程序将Visibility值传播到UI线程。这是因为每个DispatcherObject(我们的DependencyObject派生自DispatcherObject)都会将执行传播到它关联的Dispatcher。

答案 1 :(得分:0)

  1. 显示您的&#34;请等待标签&#34;一旦你点击按钮。
  2. 在异步FD.Search(index, selecteditem);
  3. 中执行您的长时间操作:Task.Run()
  4. 长操作完成后,使用ContinueWith()隐藏标签。

    private void SearchButtonActions() {
        lblWait.Visibility = Visibility.Visible;
        Task.Run(() => {
            return FD.Search(index, selecteditem);
        }).ContinueWith((Task<bool> task) => {
            Dispatcher.Invoke(() => { 
              FDItems = new ObservableCollection<Item>(FD.Items));
              lblWait.Visibility = Visibility.Hidden;
            });
        });
    }
    
  5. 如果您需要FD.Search()块中某处ContinueWith()的结果,请使用task.Result进行检索。