如何在另一个方法中动态更改 textBlock 的内容?

How to dynamically change the content of a textBlock inside another method?

我有一个由“搜索”按钮触发的搜索方法(扩展的 SQL 查询)。我希望在代码为 运行 时在 TextBlock 中显示“运行...”,并在结束时显示“完成”。理想情况下,几秒钟后“完成”消息也会被“空闲”消息取代。

我的 XAML 代码的相关部分是这样的:

<Button x:Name="MainButton" Click="searchButton_Click" Content="search" ... />
<TextBlock Name="status" Text="Idle" .../>

我的C#代码的相关部分如下:

namespace WpfApp5
{

   public partial class MainWindow : Window 
   {


        public MainWindow()
        {
        InitializeComponent();
        }


        private void searchButton_Click(object sender, RoutedEventArgs e)
        {

        this.status.Text="running...";
  
        // make connection

        string mySQLquery= "Do a lot of things here...";

  

        // show the result in a datagrid
        SqlCommand my_cmd = new SqlCommand(mySQLquery, conn);

        DataTable mydt = new DataTable();

        using (SqlDataAdapter a = new SqlDataAdapter(my_cmd))
        {
           a.Fill(mydt);
        }

        this.status.Text="done";

        }
    }
}

这段代码的作用是,当应用程序打开时,它在 TextBlock 中显示“空闲”,然后不更改它,直到搜索过程完成;然后显示“完成”。所以“运行”状态不会出现。 我想要一个对我的代码逻辑进行最少更改的解决方案。提前谢谢你。

您需要 运行 异步查询。在方法退出之前,WPF 不会更新 UI。 您可以将处理程序标记为异步并使用 Task.Run 进行 sql 查询:

private async void searchButton_Click(object sender, RoutedEventArgs e)
{
    this.status.Text="running...";

    // make connection

    string mySQLquery= "Do a lot of things here...";



    // show the result in a datagrid
    SqlCommand my_cmd = new SqlCommand(mySQLquery, conn);

    DataTable mydt = new DataTable();

    await Task.Run(() => {
       using (SqlDataAdapter a = new SqlDataAdapter(my_cmd))
       {
          a.Fill(mydt);
       }
    });

    this.status.Text="done";

    await Task.Delay(2000);
 
    this.status.Text = "idle";

}

您是 运行 UI 线程上的 searchButton_click 函数,UI 在函数完成之前不会更新。

private void searchButton_Click(object sender, RoutedEventArgs e)
{
    // starts the lambda outside the UI thread
    Task.Run(() =>
    {
        // dispatcher will execute the lambda inside the UI thread
        Application.Current.Dispatcher.Invoke(() =>
        {
            Status.Text = "running...";
        });
        Thread.Sleep(1000);
        Application.Current.Dispatcher.Invoke(() =>
        {
            Status.Text = "done";
        });
        SetDefaultPromise();
    });
}

private void SetDefaultPromise()
{
    Task.Run(() =>
    {
        Thread.Sleep(1000);
        Application.Current.Dispatcher.Invoke(() =>
        {
            Status.Text = "idle";
        });
    });
}