INotifyPropertyChanged binding label problem during update in function
-
Hello I have a problem with update of binding of a label. I have this simple class:
public partial class frTest : INotifyPropertyChanged
{
private string _message;
public string Message
{
private set
{
_message = value;
OnPropertyChanged("Message");
}
get
{
return _message;
}
}public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public frTest() { InitializeComponent(); DataContext = this; } private void WindowLoaded(object sender, RoutedEventArgs e) { Message = "test"; txtDevQty.Text = "1000"; txtDevQty.TextAlignment = TextAlignment.Center; txtDevQty.IsEnabled = false; } private void BtnNextClick(object sender, RoutedEventArgs e) { for (int i = 0; i < 1000; i++) { Message = string.Format("Tested {0} of {1}", i, 1000); Thread.Sleep(10); } }
}
I have in the xaml code a label with content binded to Message value
<Label Name="lblHint" Content="{Binding Message}" HorizontalAlignment="Center" FontFamily="verdana" FontSize="11" FontWeight="Bold" Foreground="Black" Grid.ColumnSpan="2"></Label>
The problem is that when i launch the BtnNextClick function,i see the label updated only at the end of procedure,and what i would like is to see updated in every cycle the content of the label.... How can I do? I think it's a problem between my form and the ui thread? Thanks in advance Best regards
-
Hello I have a problem with update of binding of a label. I have this simple class:
public partial class frTest : INotifyPropertyChanged
{
private string _message;
public string Message
{
private set
{
_message = value;
OnPropertyChanged("Message");
}
get
{
return _message;
}
}public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public frTest() { InitializeComponent(); DataContext = this; } private void WindowLoaded(object sender, RoutedEventArgs e) { Message = "test"; txtDevQty.Text = "1000"; txtDevQty.TextAlignment = TextAlignment.Center; txtDevQty.IsEnabled = false; } private void BtnNextClick(object sender, RoutedEventArgs e) { for (int i = 0; i < 1000; i++) { Message = string.Format("Tested {0} of {1}", i, 1000); Thread.Sleep(10); } }
}
I have in the xaml code a label with content binded to Message value
<Label Name="lblHint" Content="{Binding Message}" HorizontalAlignment="Center" FontFamily="verdana" FontSize="11" FontWeight="Bold" Foreground="Black" Grid.ColumnSpan="2"></Label>
The problem is that when i launch the BtnNextClick function,i see the label updated only at the end of procedure,and what i would like is to see updated in every cycle the content of the label.... How can I do? I think it's a problem between my form and the ui thread? Thanks in advance Best regards
The reason you're not seeing anything is because your Thread.Sleeps are locking the UI thread. If you want to see the labels, simply wrap the loop up like this:
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 1000; i++)
{
Message = string.Format("Tested {0} of {1}", i, 1000);
Thread.Sleep(10);
}
}); -
The reason you're not seeing anything is because your Thread.Sleeps are locking the UI thread. If you want to see the labels, simply wrap the loop up like this:
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 1000; i++)
{
Message = string.Format("Tested {0} of {1}", i, 1000);
Thread.Sleep(10);
}
}); -
Only if you want to pause your thread long enough to actually see the update. If you remove it, you'll flood the UI with notifications.
-
Only if you want to pause your thread long enough to actually see the update. If you remove it, you'll flood the UI with notifications.
I have tried but unfortunately using task don't solve my problem... Because my code is a little bit different of what i wrote... With this code the update of the label start only when all the iterations of the for (for (int j = 0; j < 10; j++)) are completed
public partial class frTest : INotifyPropertyChanged
{
private string _message;
public string Message
{
private set
{
_message = value;
OnPropertyChanged("Message");
}
get
{
return _message;
}
}public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public frTest() { InitializeComponent(); DataContext = this; } private void WindowLoaded(object sender, RoutedEventArgs e) { Message = "test"; txtDevQty.Text = "1000"; txtDevQty.TextAlignment = TextAlignment.Center; txtDevQty.IsEnabled = false; } public void DoSomething() { var a = 0; for (int i = 0; i < 2000000; i++) { a++; } } private void BtnNextClick(object sender, RoutedEventArgs e) { for (int j = 0; j < 10; j++) { DoSomething(); Task.Factory.StartNew(() => { try { for (int i = 0; i < 1000; i++) { Message = string.Format("Tested {0} of {1}", i, 1000); Thread.Sleep(10); } } catch (Exception ex) { } }); } }
}
-
I have tried but unfortunately using task don't solve my problem... Because my code is a little bit different of what i wrote... With this code the update of the label start only when all the iterations of the for (for (int j = 0; j < 10; j++)) are completed
public partial class frTest : INotifyPropertyChanged
{
private string _message;
public string Message
{
private set
{
_message = value;
OnPropertyChanged("Message");
}
get
{
return _message;
}
}public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public frTest() { InitializeComponent(); DataContext = this; } private void WindowLoaded(object sender, RoutedEventArgs e) { Message = "test"; txtDevQty.Text = "1000"; txtDevQty.TextAlignment = TextAlignment.Center; txtDevQty.IsEnabled = false; } public void DoSomething() { var a = 0; for (int i = 0; i < 2000000; i++) { a++; } } private void BtnNextClick(object sender, RoutedEventArgs e) { for (int j = 0; j < 10; j++) { DoSomething(); Task.Factory.StartNew(() => { try { for (int i = 0; i < 1000; i++) { Message = string.Format("Tested {0} of {1}", i, 1000); Thread.Sleep(10); } } catch (Exception ex) { } }); } }
}
And what else would you expect it to do? You aren't actually starting to update Message until you have completed the other loop. Just drop your outer loop into the task factory.
-
And what else would you expect it to do? You aren't actually starting to update Message until you have completed the other loop. Just drop your outer loop into the task factory.
-
I cannot do it because in reality my DoSomething function do some work and start a thread that do some long operations. For this reason i need to update the label for have a feedback of where is my routine arrived
Look, I cannot read your mind about what you are trying to do. You cannot keep drip feeding things through. It's simple enough, you need to update your label text from a none UI thread, so you can simply spawn that off in its own TaskFactory. In your example, you aren't starting off the update of the label until you have completed DoSomething. Step away from the keyboard right now, and actually design the interactions you need rather than throwing things on here that don't actually match what you're trying to do.