Reputation: 1898
The same questions has been asked many times on this site and I have read most of them. But I have a special problem (maybe?) that couldn't figure it out after hours of struggling and reading SO posts.
The problem is -simply explained, I have a WPF form which contains a Connect
button. If this button is pressed a textblock must appear on that form, displaying the word "Connecting...". Upon pressing the button, some handshaking operations are done in the associated C# code which takes some time. If the program fails to connect, the textblock must change to "Failed!". Otherwise, it changes to "Succeed."
Now for this simple problem, I wrote in my XAML:
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="connecting" Content="Connect" FontWeight="Bold" Click="startConnection"
Width="60" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0"/>
<TextBlock x:Name="comm_stat" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Content}"/>
</Grid>
</Window>
And the C# code (inspired by this answer):
using System;
using System.Text;
using System.Windows;
using System.ComponentModel;
namespace WpfTest
{
public class DynamicObj : INotifyPropertyChanged
{
public DynamicObj() : this(string.Empty) { }
public DynamicObj(string txt) { Content = txt; }
private string _name;
public string Content
{
get { return _name; }
set {
_name = value;
OnPropertyChanged("Content");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
comm_stat.DataContext = new DynamicObj();
}
private void startConnection(object sender, RoutedEventArgs e)
{
comm_stat.Text = "Connecting...";
bool connect2device = false;
// do the handshaking operations. the result is then assigned to connect2device
comm_stat.Text = connect2device ? "Succeed." : "Failed!";
// some other operations
}
}
}
Now the problem is, whenever I click the button, no text is appeared in the textblock. Because the program waits for the startConnection
method to reach its end and then updates the bonded textblock. But I want the textblock to change right after pressing the button. How can I do this?
Upvotes: 1
Views: 1847
Reputation: 3305
You can use BackgroundWorker
as such:
bool connect2device = false;
private void startConnection(object sender, RoutedEventArgs e)
{
comm_stat.Text = "Connecting...";
// do the handshaking operations. the result is then assigned to connect2device
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += Completed;
worker.RunWorkerAsync();
}
private void Completed(object sender, RunWorkerCompletedEventArgs e)
{
comm_stat.Text = connect2device ? "Succeed." : "Failed!";
}
private void DoWork(object sender, DoWorkEventArgs e)
{
//Change with actual work.
Thread.Sleep(1000);
connect2device = true;
}
One side note is that you actually do not use bindings to change the text. comm_stat.Text = "Connecting...";
sets the text property directly and the DynamicObj
object is not used at all. It might be good for you to read a few tutorial on MVVM.
Upvotes: 3