How do I refresh visual control properties (TextBlock.text) set inside a loop?
With each loop iteration, I want to visually update the text of a textblock. My problem is that the WPF window or control does not visually refresh until the loop is complete.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
In VB6, I would call DoEvents()
or control.Refresh
. At the moment I'd just like a quick and dirty solution similar to DoEvents()
, but I'd also like to know about alternatives or the "right" way to do this. Is there a simple binding statement I could add? What is the syntax?
Thanks in advance.
wpf wpf-controls binding inotifypropertychanged
add a comment |
With each loop iteration, I want to visually update the text of a textblock. My problem is that the WPF window or control does not visually refresh until the loop is complete.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
In VB6, I would call DoEvents()
or control.Refresh
. At the moment I'd just like a quick and dirty solution similar to DoEvents()
, but I'd also like to know about alternatives or the "right" way to do this. Is there a simple binding statement I could add? What is the syntax?
Thanks in advance.
wpf wpf-controls binding inotifypropertychanged
add a comment |
With each loop iteration, I want to visually update the text of a textblock. My problem is that the WPF window or control does not visually refresh until the loop is complete.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
In VB6, I would call DoEvents()
or control.Refresh
. At the moment I'd just like a quick and dirty solution similar to DoEvents()
, but I'd also like to know about alternatives or the "right" way to do this. Is there a simple binding statement I could add? What is the syntax?
Thanks in advance.
wpf wpf-controls binding inotifypropertychanged
With each loop iteration, I want to visually update the text of a textblock. My problem is that the WPF window or control does not visually refresh until the loop is complete.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
In VB6, I would call DoEvents()
or control.Refresh
. At the moment I'd just like a quick and dirty solution similar to DoEvents()
, but I'd also like to know about alternatives or the "right" way to do this. Is there a simple binding statement I could add? What is the syntax?
Thanks in advance.
wpf wpf-controls binding inotifypropertychanged
wpf wpf-controls binding inotifypropertychanged
edited Nov 21 '18 at 6:04
Lauren Van Sloun
1,02921219
1,02921219
asked Mar 31 '11 at 18:01
DeveloperDanDeveloperDan
2,31893054
2,31893054
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
If you really want the quick and dirty implementation and don't care about maintaining the product in the future or about the user experience, you can just add a reference to System.Windows.Forms and call System.Windows.Forms.Application.DoEvents()
:
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
The downside is that it's really really bad. You're going to lock up the UI during the Thread.Sleep(), which annoys the user, and you could end up with unpredictable results depending on the complexity of the program (I have seen one application where two methods were running on the UI thread, each one calling DoEvents() repeatedly...).
This is how it should be done:
- Any time your application has to wait for something to happen (ie a disk read, a web service call, or a Sleep()), it should be on a separate thread.
- You should not set TextBlock.Text manually - bind it to a property and implement INotifyPropertyChanged.
Here is an example showing the functionality you've asked for. It only takes a few seconds longer to write and it's so much easier to work with - and it doesn't lock up the UI.
Xaml:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The code might seem a bit complicated, but it's a cornerstone of WPF, and it comes together with a bit of practice - it's well worth learning.
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for.net 3.5 threading
to find the legacy mechanisms.
– Greg Sansom
Nov 11 '11 at 5:01
add a comment |
I tried the solution exposed here and it didn't work for me until I added the following:
Create an extension method and make sure you reference its containing assembly from your project.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Then call it right after RaisePropertyChanged
:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
That will force the UI thread to take control for a small while and dispatch any pending changes on the UI element.
add a comment |
This is how you would do it normally:
ThreadPool.QueueUserWorkItem(ignored =>
{
for (int i = 0; i < 50; i++) {
System.Threading.Thread.Sleep(100);
myTextBlock.Dispatcher.BeginInvoke(
new Action(() => myTextBlock.Text = i.ToString()));
}
});
This delegates the operation to a worker pool thread, which allows your UI thread to process messages (and keeps your UI from freezing). Because the worker thread cannot access myTextBlock
directly, it needs to use BeginInvoke
.
Although this approach is not "the WPF way" to do things, there's nothing wrong with it (and indeed, I don't believe there's any alternative with this little code). But another way to do things would go like this:
- Bind the
Text
of theTextBlock
to a property of some object that implementsINotifyPropertyChanged
- From within the loop, set that property to the value you want; the changes will be propagated to the UI automatically
- No need for threads,
BeginInvoke
, or anything else
If you already have an object and the UI has access to it, this is as simple as writing Text="{Binding MyObject.MyProperty}"
.
Update: For example, let's assume you have this:
class Foo : INotifyPropertyChanged // you need to implement the interface
{
private int number;
public int Number {
get { return this.number; }
set {
this.number = value;
// Raise PropertyChanged here
}
}
}
class MyWindow : Window
{
public Foo PropertyName { get; set; }
}
The binding would be done like this in XAML:
<TextBlock Text="{Binding PropertyName.Number}" />
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
|
show 1 more comment
You can do Dispatcher.BeginInvoke in order to do a thread context-switch so that the rendering thread could do its job.
However, this is not the right way for such things. You should use Animation + Binding for things like that, as this is the hack-free way of doing things like that in WPF.
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
|
show 2 more comments
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Running the above code inside a background worker component and using a binding updatesourcetrigeer
as propertychanged
will reflect the changes immediately in the UI control.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5504244%2fhow-do-i-refresh-visual-control-properties-textblock-text-set-inside-a-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you really want the quick and dirty implementation and don't care about maintaining the product in the future or about the user experience, you can just add a reference to System.Windows.Forms and call System.Windows.Forms.Application.DoEvents()
:
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
The downside is that it's really really bad. You're going to lock up the UI during the Thread.Sleep(), which annoys the user, and you could end up with unpredictable results depending on the complexity of the program (I have seen one application where two methods were running on the UI thread, each one calling DoEvents() repeatedly...).
This is how it should be done:
- Any time your application has to wait for something to happen (ie a disk read, a web service call, or a Sleep()), it should be on a separate thread.
- You should not set TextBlock.Text manually - bind it to a property and implement INotifyPropertyChanged.
Here is an example showing the functionality you've asked for. It only takes a few seconds longer to write and it's so much easier to work with - and it doesn't lock up the UI.
Xaml:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The code might seem a bit complicated, but it's a cornerstone of WPF, and it comes together with a bit of practice - it's well worth learning.
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for.net 3.5 threading
to find the legacy mechanisms.
– Greg Sansom
Nov 11 '11 at 5:01
add a comment |
If you really want the quick and dirty implementation and don't care about maintaining the product in the future or about the user experience, you can just add a reference to System.Windows.Forms and call System.Windows.Forms.Application.DoEvents()
:
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
The downside is that it's really really bad. You're going to lock up the UI during the Thread.Sleep(), which annoys the user, and you could end up with unpredictable results depending on the complexity of the program (I have seen one application where two methods were running on the UI thread, each one calling DoEvents() repeatedly...).
This is how it should be done:
- Any time your application has to wait for something to happen (ie a disk read, a web service call, or a Sleep()), it should be on a separate thread.
- You should not set TextBlock.Text manually - bind it to a property and implement INotifyPropertyChanged.
Here is an example showing the functionality you've asked for. It only takes a few seconds longer to write and it's so much easier to work with - and it doesn't lock up the UI.
Xaml:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The code might seem a bit complicated, but it's a cornerstone of WPF, and it comes together with a bit of practice - it's well worth learning.
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for.net 3.5 threading
to find the legacy mechanisms.
– Greg Sansom
Nov 11 '11 at 5:01
add a comment |
If you really want the quick and dirty implementation and don't care about maintaining the product in the future or about the user experience, you can just add a reference to System.Windows.Forms and call System.Windows.Forms.Application.DoEvents()
:
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
The downside is that it's really really bad. You're going to lock up the UI during the Thread.Sleep(), which annoys the user, and you could end up with unpredictable results depending on the complexity of the program (I have seen one application where two methods were running on the UI thread, each one calling DoEvents() repeatedly...).
This is how it should be done:
- Any time your application has to wait for something to happen (ie a disk read, a web service call, or a Sleep()), it should be on a separate thread.
- You should not set TextBlock.Text manually - bind it to a property and implement INotifyPropertyChanged.
Here is an example showing the functionality you've asked for. It only takes a few seconds longer to write and it's so much easier to work with - and it doesn't lock up the UI.
Xaml:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The code might seem a bit complicated, but it's a cornerstone of WPF, and it comes together with a bit of practice - it's well worth learning.
If you really want the quick and dirty implementation and don't care about maintaining the product in the future or about the user experience, you can just add a reference to System.Windows.Forms and call System.Windows.Forms.Application.DoEvents()
:
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyTextBlock.Text = i.ToString();
System.Windows.Forms.Application.DoEvents();
}
The downside is that it's really really bad. You're going to lock up the UI during the Thread.Sleep(), which annoys the user, and you could end up with unpredictable results depending on the complexity of the program (I have seen one application where two methods were running on the UI thread, each one calling DoEvents() repeatedly...).
This is how it should be done:
- Any time your application has to wait for something to happen (ie a disk read, a web service call, or a Sleep()), it should be on a separate thread.
- You should not set TextBlock.Text manually - bind it to a property and implement INotifyPropertyChanged.
Here is an example showing the functionality you've asked for. It only takes a few seconds longer to write and it's so much easier to work with - and it doesn't lock up the UI.
Xaml:
<StackPanel>
<TextBlock Name="MyTextBlock" Text="{Binding Path=MyValue}"></TextBlock>
<Button Click="Button_Click">OK</Button>
</StackPanel>
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
MyValue = i.ToString();
}
});
}
private string myValue;
public string MyValue
{
get { return myValue; }
set
{
myValue = value;
RaisePropertyChanged("MyValue");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
The code might seem a bit complicated, but it's a cornerstone of WPF, and it comes together with a bit of practice - it's well worth learning.
edited Apr 2 '11 at 3:11
answered Apr 1 '11 at 0:01
Greg SansomGreg Sansom
15.6k54866
15.6k54866
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for.net 3.5 threading
to find the legacy mechanisms.
– Greg Sansom
Nov 11 '11 at 5:01
add a comment |
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for.net 3.5 threading
to find the legacy mechanisms.
– Greg Sansom
Nov 11 '11 at 5:01
1
1
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Excellent! The other answers are great, but I understand this one best and it includes the quick and dirty solution I asked for. To make Greg's solution work I added: using System.ComponentModel; (and) using System.Threading.Tasks;. Don't forget to reference System.Windows.Forms to make the DoEvents() solution work. I've learned a lot. Thanks!
– DeveloperDan
Apr 1 '11 at 13:40
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Whats this code look like in .net 3.5 (specifically Task.Factory.StartNew)
– David
Oct 27 '11 at 17:42
Task.Factory.StartNew was introduced in .net 4. Just search for
.net 3.5 threading
to find the legacy mechanisms.– Greg Sansom
Nov 11 '11 at 5:01
Task.Factory.StartNew was introduced in .net 4. Just search for
.net 3.5 threading
to find the legacy mechanisms.– Greg Sansom
Nov 11 '11 at 5:01
add a comment |
I tried the solution exposed here and it didn't work for me until I added the following:
Create an extension method and make sure you reference its containing assembly from your project.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Then call it right after RaisePropertyChanged
:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
That will force the UI thread to take control for a small while and dispatch any pending changes on the UI element.
add a comment |
I tried the solution exposed here and it didn't work for me until I added the following:
Create an extension method and make sure you reference its containing assembly from your project.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Then call it right after RaisePropertyChanged
:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
That will force the UI thread to take control for a small while and dispatch any pending changes on the UI element.
add a comment |
I tried the solution exposed here and it didn't work for me until I added the following:
Create an extension method and make sure you reference its containing assembly from your project.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Then call it right after RaisePropertyChanged
:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
That will force the UI thread to take control for a small while and dispatch any pending changes on the UI element.
I tried the solution exposed here and it didn't work for me until I added the following:
Create an extension method and make sure you reference its containing assembly from your project.
public static void Refresh(this UIElement uiElement){
uiElement.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => { }));
}
Then call it right after RaisePropertyChanged
:
RaisePropertyChanged("MyValue");
myTextBlock.Refresh();
That will force the UI thread to take control for a small while and dispatch any pending changes on the UI element.
edited Nov 21 '18 at 6:54
abhirathore2006
2,2321626
2,2321626
answered May 31 '11 at 18:23
JazzJazz
1,0501411
1,0501411
add a comment |
add a comment |
This is how you would do it normally:
ThreadPool.QueueUserWorkItem(ignored =>
{
for (int i = 0; i < 50; i++) {
System.Threading.Thread.Sleep(100);
myTextBlock.Dispatcher.BeginInvoke(
new Action(() => myTextBlock.Text = i.ToString()));
}
});
This delegates the operation to a worker pool thread, which allows your UI thread to process messages (and keeps your UI from freezing). Because the worker thread cannot access myTextBlock
directly, it needs to use BeginInvoke
.
Although this approach is not "the WPF way" to do things, there's nothing wrong with it (and indeed, I don't believe there's any alternative with this little code). But another way to do things would go like this:
- Bind the
Text
of theTextBlock
to a property of some object that implementsINotifyPropertyChanged
- From within the loop, set that property to the value you want; the changes will be propagated to the UI automatically
- No need for threads,
BeginInvoke
, or anything else
If you already have an object and the UI has access to it, this is as simple as writing Text="{Binding MyObject.MyProperty}"
.
Update: For example, let's assume you have this:
class Foo : INotifyPropertyChanged // you need to implement the interface
{
private int number;
public int Number {
get { return this.number; }
set {
this.number = value;
// Raise PropertyChanged here
}
}
}
class MyWindow : Window
{
public Foo PropertyName { get; set; }
}
The binding would be done like this in XAML:
<TextBlock Text="{Binding PropertyName.Number}" />
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
|
show 1 more comment
This is how you would do it normally:
ThreadPool.QueueUserWorkItem(ignored =>
{
for (int i = 0; i < 50; i++) {
System.Threading.Thread.Sleep(100);
myTextBlock.Dispatcher.BeginInvoke(
new Action(() => myTextBlock.Text = i.ToString()));
}
});
This delegates the operation to a worker pool thread, which allows your UI thread to process messages (and keeps your UI from freezing). Because the worker thread cannot access myTextBlock
directly, it needs to use BeginInvoke
.
Although this approach is not "the WPF way" to do things, there's nothing wrong with it (and indeed, I don't believe there's any alternative with this little code). But another way to do things would go like this:
- Bind the
Text
of theTextBlock
to a property of some object that implementsINotifyPropertyChanged
- From within the loop, set that property to the value you want; the changes will be propagated to the UI automatically
- No need for threads,
BeginInvoke
, or anything else
If you already have an object and the UI has access to it, this is as simple as writing Text="{Binding MyObject.MyProperty}"
.
Update: For example, let's assume you have this:
class Foo : INotifyPropertyChanged // you need to implement the interface
{
private int number;
public int Number {
get { return this.number; }
set {
this.number = value;
// Raise PropertyChanged here
}
}
}
class MyWindow : Window
{
public Foo PropertyName { get; set; }
}
The binding would be done like this in XAML:
<TextBlock Text="{Binding PropertyName.Number}" />
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
|
show 1 more comment
This is how you would do it normally:
ThreadPool.QueueUserWorkItem(ignored =>
{
for (int i = 0; i < 50; i++) {
System.Threading.Thread.Sleep(100);
myTextBlock.Dispatcher.BeginInvoke(
new Action(() => myTextBlock.Text = i.ToString()));
}
});
This delegates the operation to a worker pool thread, which allows your UI thread to process messages (and keeps your UI from freezing). Because the worker thread cannot access myTextBlock
directly, it needs to use BeginInvoke
.
Although this approach is not "the WPF way" to do things, there's nothing wrong with it (and indeed, I don't believe there's any alternative with this little code). But another way to do things would go like this:
- Bind the
Text
of theTextBlock
to a property of some object that implementsINotifyPropertyChanged
- From within the loop, set that property to the value you want; the changes will be propagated to the UI automatically
- No need for threads,
BeginInvoke
, or anything else
If you already have an object and the UI has access to it, this is as simple as writing Text="{Binding MyObject.MyProperty}"
.
Update: For example, let's assume you have this:
class Foo : INotifyPropertyChanged // you need to implement the interface
{
private int number;
public int Number {
get { return this.number; }
set {
this.number = value;
// Raise PropertyChanged here
}
}
}
class MyWindow : Window
{
public Foo PropertyName { get; set; }
}
The binding would be done like this in XAML:
<TextBlock Text="{Binding PropertyName.Number}" />
This is how you would do it normally:
ThreadPool.QueueUserWorkItem(ignored =>
{
for (int i = 0; i < 50; i++) {
System.Threading.Thread.Sleep(100);
myTextBlock.Dispatcher.BeginInvoke(
new Action(() => myTextBlock.Text = i.ToString()));
}
});
This delegates the operation to a worker pool thread, which allows your UI thread to process messages (and keeps your UI from freezing). Because the worker thread cannot access myTextBlock
directly, it needs to use BeginInvoke
.
Although this approach is not "the WPF way" to do things, there's nothing wrong with it (and indeed, I don't believe there's any alternative with this little code). But another way to do things would go like this:
- Bind the
Text
of theTextBlock
to a property of some object that implementsINotifyPropertyChanged
- From within the loop, set that property to the value you want; the changes will be propagated to the UI automatically
- No need for threads,
BeginInvoke
, or anything else
If you already have an object and the UI has access to it, this is as simple as writing Text="{Binding MyObject.MyProperty}"
.
Update: For example, let's assume you have this:
class Foo : INotifyPropertyChanged // you need to implement the interface
{
private int number;
public int Number {
get { return this.number; }
set {
this.number = value;
// Raise PropertyChanged here
}
}
}
class MyWindow : Window
{
public Foo PropertyName { get; set; }
}
The binding would be done like this in XAML:
<TextBlock Text="{Binding PropertyName.Number}" />
edited Apr 1 '11 at 11:52
answered Mar 31 '11 at 18:07
JonJon
347k60611716
347k60611716
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
|
show 1 more comment
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
The only thing that this actually does is the Dispatcher.BeginInvoke. Which I had already said earlier...
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
@EladKatz: Moving the code to another thread does nothing? I guess so, if having your UI frozen for stretches of 100msec counts as "nothing".
– Jon
Mar 31 '11 at 18:16
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
but that was not the question, and it's pretty obvious...
– Elad Katz
Mar 31 '11 at 18:17
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
+1 for the 3 steps in the second part of your answer. this works perfectly and is very easy to implement. This is an essential part of MVVM as well.
– xdumaine
Mar 31 '11 at 18:39
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
While your code sample works nicely, it's too complex for me to remember. What binding syntax could I use for this.MyProperty? My quick and dirty form is using only code behind - no external objects. I haven't gotten the binding syntax right. How can I replace your MyObject.MyProperty with a binding statement that references a property on my WPF Window? Instead of setting myTextBlock.text directly I would update the Window property which in turn would update the bound textblock.text.
– DeveloperDan
Mar 31 '11 at 18:52
|
show 1 more comment
You can do Dispatcher.BeginInvoke in order to do a thread context-switch so that the rendering thread could do its job.
However, this is not the right way for such things. You should use Animation + Binding for things like that, as this is the hack-free way of doing things like that in WPF.
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
|
show 2 more comments
You can do Dispatcher.BeginInvoke in order to do a thread context-switch so that the rendering thread could do its job.
However, this is not the right way for such things. You should use Animation + Binding for things like that, as this is the hack-free way of doing things like that in WPF.
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
|
show 2 more comments
You can do Dispatcher.BeginInvoke in order to do a thread context-switch so that the rendering thread could do its job.
However, this is not the right way for such things. You should use Animation + Binding for things like that, as this is the hack-free way of doing things like that in WPF.
You can do Dispatcher.BeginInvoke in order to do a thread context-switch so that the rendering thread could do its job.
However, this is not the right way for such things. You should use Animation + Binding for things like that, as this is the hack-free way of doing things like that in WPF.
answered Mar 31 '11 at 18:05
Elad KatzElad Katz
6,08732962
6,08732962
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
|
show 2 more comments
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
1
1
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
You can only use animations if the UI updates are pure eye candy. You can't do it if you actually want the UI to reflect the state of some process.
– Jon
Mar 31 '11 at 18:09
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
I beg to differ. Animation can do that also. the only thing u need to do is implement a DP where u want the animation to occur.
– Elad Katz
Mar 31 '11 at 18:11
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
@EladKatz: You can bind to a property and use an appropriate converter to bring about UI changes, sure. Where does the animation come in?
– Jon
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
you animate the DP. the TextBox would be bound to that DP.
– Elad Katz
Mar 31 '11 at 18:14
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
@EladKatz: Why would you animate it when you want it to reflect the state of a process?
– Jon
Mar 31 '11 at 18:21
|
show 2 more comments
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Running the above code inside a background worker component and using a binding updatesourcetrigeer
as propertychanged
will reflect the changes immediately in the UI control.
add a comment |
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Running the above code inside a background worker component and using a binding updatesourcetrigeer
as propertychanged
will reflect the changes immediately in the UI control.
add a comment |
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Running the above code inside a background worker component and using a binding updatesourcetrigeer
as propertychanged
will reflect the changes immediately in the UI control.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
Running the above code inside a background worker component and using a binding updatesourcetrigeer
as propertychanged
will reflect the changes immediately in the UI control.
edited Nov 21 '18 at 6:05
Lauren Van Sloun
1,02921219
1,02921219
answered May 7 '14 at 16:21
PadmanabanPadmanaban
305
305
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5504244%2fhow-do-i-refresh-visual-control-properties-textblock-text-set-inside-a-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown