Reputation: 2374
Thank you for your time. I have a such a problem with WPF... it updates UI, it updates it only when the method (triggered by the button click) reaches its end. However, in my real app I need to update UI immediately to see info.
I tried to read tutorials and posts and I am ready to give up.... I would appreciate any ideas why it happens and what to do :-).
<TextBox Text="{Binding FirstName}"/>
<Button Content="Run" Click="Button_Click" />
public partial class MainWindow
{
public Person Person = new Person();
public MainWindow()
{
InitializeComponent();
DataContext = Person;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Person.FirstName = "John";
Thread.Sleep(10000);
///// Only Here I can see the update.
}
}
And DataContext is:
public class Person:INotifyPropertyChanged
{
private string _FirstName;
public string FirstName
{
get { return _FirstName; }
set
{
if (_FirstName == value)
return;
_FirstName = value;
OnPropertyChanged("FirstName");
}
}
....
Standard OnProertyChanged implementation.
Upvotes: 2
Views: 1647
Reputation: 102723
You should never block the UI thread using Sleep
. Instead, you may want to put that part of the code on a background thread. Eg, using Task.Factory.StartNew:
private void Button_Click(object sender, RoutedEventArgs e)
{
Person.FirstName = "John";
Task.Factory.StartNew( () => {
Thread.Sleep(10000);
// ...
});
}
Note that you can't make any other UI changes inside that thread. If you need to, send them back to the UI thread using Dispatcher.BeginInvoke
.
For example, as per the comment:
Person.FirstName = "John";
Task.Factory.StartNew( () => {
foreach (string mlsNumber in ourMlses)
{
Listing listing = sourceSite.ParseByMls(mlsNumber);
if (listing != null)
{
var successDb = sourceSite.UpdateListing(listing);
if (!successDb)
{
throw new Exception("Db error");
}
Dispatcher.BeginInvoke( () => {
// UI update that listing have been added to the DB
});
}
}
} );
Upvotes: 2
Reputation: 8934
I assume you're running a lengthy operation in Button_Click
method and want to update UI first with a new FirstName. Try to wrap up your FirstName initialization in Dispatcher.Invoke method:
private void Button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => {
Person.FirstName = "John";
}));
// Run a lengthy operation here
}
It will trigger UI update on PropertyChanged event in the same manner as it was after exiting the Button_Click method.
P.S. However, all code you see here is quite bad practice and I would murder a developer who wrote it. But it may suit some academic purposes. To make a proper solution, it's better to use Commands and handle it in ViewModel instead of click handlers.
Upvotes: 0