如何刷新循环内设置的视觉控件属性 (TextBlock.text)? [英] How do I refresh visual control properties (TextBlock.text) set inside a loop?

查看:22
本文介绍了如何刷新循环内设置的视觉控件属性 (TextBlock.text)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在每次循环迭代中,我想直观地更新文本块的文本.我的问题是 WPF 窗口或控件在循环完成之前不会在视觉上刷新.

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

在 VB6 中,我会调用 DoEvents()control.Refresh.目前我只是想要一个类似于 DoEvents() 的快速而肮脏的解决方案,但我也想知道替代方案或正确"的方法来做到这一点.我可以添加一个简单的绑定语句吗?语法是什么?提前致谢.

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.

推荐答案

如果你真的想要快速而肮脏的实施并且不关心未来的产品维护或用户体验,您只需添加对 System.Windows.Forms 的引用并调用 System.Windows.Forms.Application.DoEvents():

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

缺点是真的很糟糕.您将在 Thread.Sleep() 期间锁定 UI,这会惹恼用户,并且根据程序的复杂性,您最终可能会得到不可预测的结果(我曾见过一个应用程序,其中两种方法正在运行UI线程,每一个都重复调用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...).

  1. 任何时候您的应用程序必须等待某些事情发生(即磁盘读取、Web 服务调用或 Sleep()),它应该在一个单独的线程上.
  2. 您不应手动设置 TextBlock.Text - 将其绑定到属性并实现 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>

代码隐藏:

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

代码可能看起来有点复杂,但它是 WPF 的基石,它结合了一些实践 - 非常值得学习.

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.

这篇关于如何刷新循环内设置的视觉控件属性 (TextBlock.text)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆