C# 如何动态更新我的UI

C# 如何动态更新我的UI,c#,wpf,task,dynamic-ui,C#,Wpf,Task,Dynamic Ui,我已经研究了几个有关动态UI的问题,但我仍然不明白我遗漏了什么。此外,我还学习了关于如何使用任务的教程,但我的理解仍然有限。以下是我想要实现的目标: 我的应用程序正在幕后进行一些工作,但我希望我的UI能够响应。我尝试了以下方法(请参见代码),但在调用dispatcher之前,UI不会开始更新。我希望UI状态为: 正在创建…--单击CreatePivotTable按钮后 正在建立连接…——调用provider.GetReportData方法之前 连接成功或连接失败取决于结果 完成了 <!-

我已经研究了几个有关动态UI的问题,但我仍然不明白我遗漏了什么。此外,我还学习了关于如何使用任务的教程,但我的理解仍然有限。以下是我想要实现的目标:

我的应用程序正在幕后进行一些工作,但我希望我的UI能够响应。我尝试了以下方法(请参见代码),但在调用dispatcher之前,UI不会开始更新。我希望UI状态为:

  • 正在创建…--单击CreatePivotTable按钮后
  • 正在建立连接…——调用provider.GetReportData方法之前
  • 连接成功或连接失败取决于结果
  • 完成了

     <!-- language: lang-cs -->
     private void CreatePivotTableButton(object sender, RoutedEventArgs e)
    {
    
        this.StatusToBeDisplayed.Content = "Creating...";
        this.DescriptionLabel.IsEnabled = false;
        this.TextBlockBorder.IsEnabled = true; 
    
        List<CombinedData> items = (List<CombinedData>)CustomerComboBox.ItemsSource;
        List<int> selectedItems = new List<int>();
        foreach (CombinedData item in items)
        {
            if (item.IsSelected)
            {
                selectedItems.Add(item.ReferenceId);
            }
        }
    
        PCTProvider provider = new PCTProvider();
        ExportToExcel export = new ExportToExcel();
    
        ExcelAutomation excelAutomation = new ExcelAutomation();
    
        this.ResultTextBlock.Text = "Establishing Connection";
        DataTable generateReportDataTable = provider.GetReportData(selectedItems);
        Excel.Workbook workbook = export.ExportDataTableToExcel(generateReportDataTable);
        Task updateTask = Task.Factory.StartNew(() =>
        {
            Dispatcher.Invoke(new Action(() => excelAutomation.CreatePivotTable(workbook)));
        }).ContinueWith(result =>
        {
            Dispatcher.Invoke(new Action(() => this.StatusToBeDisplayed.Content = "Done!"));
            Dispatcher.Invoke(new Action(() => OriginalStatus()));
        }, TaskScheduler.FromCurrentSynchronizationContext());
    
    }
    
    
    私有void CreatePivotTableButton(对象发送器,RoutedEventArgs e)
    {
    this.StatusToBeDisplayed.Content=“创建…”;
    this.DescriptionLabel.IsEnabled=false;
    this.TextBlockBorder.IsEnabled=true;
    列表项=(列表)CustomerComboBox.ItemsSource;
    List selectedItems=新建列表();
    foreach(项目中的组合数据项)
    {
    如果(项目.已选定)
    {
    选择editems.Add(item.ReferenceId);
    }
    }
    PCTProvider provider=新PCTProvider();
    ExportToExcel export=新的ExportToExcel();
    ExcelAutomation=新的ExcelAutomation();
    this.ResultTextBlock.Text=“建立连接”;
    DataTable generateReportDataTable=provider.GetReportData(selectedItems);
    Excel.Workbook工作簿=export.ExportDataTableToExcel(generateReportDataTable);
    任务更新任务=Task.Factory.StartNew(()=>
    {
    调用(新操作(()=>excelAutomation.CreatePivotTable(工作簿));
    }).ContinueWith(结果=>
    {
    Invoke(新操作(()=>this.StatusToBeDisplayed.Content=“Done!”);
    Invoke(新操作(()=>OriginalStatus());
    },TaskScheduler.FromCurrentSynchronizationContext());
    }
    

  • 我非常感谢你的时间和帮助

    我认为您不需要与和/或可能的
    任务调度器
    通过在任务中执行工作,您可以让UI线程响应消息泵。 您可能希望将
    CreatePivotTableButton
    的更多工作移到任务中

    请尝试以下方法:

    private void CreatePivotTableButton(object sender, RoutedEventArgs e)
    {
    
        this.StatusToBeDisplayed.Content = "Creating...";
        this.DescriptionLabel.IsEnabled = false;
        this.TextBlockBorder.IsEnabled = true; 
        // move the rest of the code into your Task to perform the work off the UI thread
        Task updateTask = Task.Factory.StartNew(() =>
        {
            List<CombinedData> items = (List<CombinedData>)CustomerComboBox.ItemsSource;
            List<int> selectedItems = new List<int>();
            foreach (CombinedData item in items)
            {
                if (item.IsSelected)
                {
                    selectedItems.Add(item.ReferenceId);
                }
            }
    
            PCTProvider provider = new PCTProvider();
            ExportToExcel export = new ExportToExcel();
    
            ExcelAutomation excelAutomation = new ExcelAutomation();
    
            Dispatcher.Invoke(new Action(() => this.ResultTextBlock.Text = "Establishing Connection"));
            DataTable generateReportDataTable = provider.GetReportData(selectedItems);
            Excel.Workbook workbook = export.ExportDataTableToExcel(generateReportDataTable);
    
            excelAutomation.CreatePivotTable(workbook);
            Dispatcher.Invoke(new Action(() => this.StatusToBeDisplayed.Content = "Done!"));
            Dispatcher.Invoke(new Action(() => OriginalStatus()));
        });
    }
    
    private void CreatePivotTableButton(对象发送方,RoutedEventTarget e)
    {
    this.StatusToBeDisplayed.Content=“创建…”;
    this.DescriptionLabel.IsEnabled=false;
    this.TextBlockBorder.IsEnabled=true;
    //将其余的代码移到任务中,以执行UI线程之外的工作
    任务更新任务=Task.Factory.StartNew(()=>
    {
    列表项=(列表)CustomerComboBox.ItemsSource;
    List selectedItems=新建列表();
    foreach(项目中的组合数据项)
    {
    如果(项目.已选定)
    {
    选择editems.Add(item.ReferenceId);
    }
    }
    PCTProvider provider=新PCTProvider();
    ExportToExcel export=新的ExportToExcel();
    ExcelAutomation=新的ExcelAutomation();
    Invoke(新操作(()=>this.ResultTextBlock.Text=“建立连接”);
    DataTable generateReportDataTable=provider.GetReportData(selectedItems);
    Excel.Workbook工作簿=export.ExportDataTableToExcel(generateReportDataTable);
    excelAutomation.CreatePivotTable(工作簿);
    Invoke(新操作(()=>this.StatusToBeDisplayed.Content=“Done!”);
    Invoke(新操作(()=>OriginalStatus());
    });
    }
    
    您可能希望将代码分解为按钮事件可以调用的较小方法。然后,在每次方法调用之前,您都要更新UI,告诉用户将要发生什么。这些将立即触发,因为它们甚至在调用真正的worker方法之前发生。如果您想将这些都放在一个方法中,那么您可以尝试使用
    Application.DoEvents
    。这只是告诉运行时它应该休息一下,看看是否还有其他东西在等待运行(比如更新表单)。UI不应该在单击按钮后立即更新为“创建…”吗?我将用一些小方法来分解它,看看这是否有帮助。谢谢,这只是因为它是方法中的第一个,并不意味着处理器将有机会完成所涉及的实际工作。这就是doevents所做的,但使用它不再是好的实践。您可能需要研究异步编码:@Oliver您解决问题了吗?@chaddienhart再次感谢您的帮助。它就像一个符咒。关于更多的问题,我需要做什么来更新UI。换句话说,我计划添加一个文本块,我想添加描述幕后发生的事情的文本。我是否需要使用另一个Dispatcher.Invoke,还是应该创建一个处理它的新方法?再次感谢你的帮助!