简体   繁体   中英

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

I have a search method (an extended SQL query within) which is triggered by a "search" button. I wish to show "Running..." in a TextBlock while the code is running and to show "Done" when it ends. Ideally the "Done" message also replaced by an "Idle" message after a few seconds.

Relevant part of my XAML code is this:

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

and the relevant part of my C# code is as follows:

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";

        }
    }
}

What this code does is that it shows "idle" in TextBlock when the app opens and then doesn't change it, till the search process is done; and then shows "done". So the "running" state doesn't appear. I would like to have a solution with minimal changes in the logic of my code. Thank you in advance.

You need to run your query asynchronously. WPF won't update UI until method is exited. You can mark you handler as async and use Task.Run to make sql query:

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";

}

You're running the searchButton_click function on the UI thread, the UI won't update until the function is done.

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";
        });
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM