c# - 文本更新未反射(reflect)在 WPF TextBlock 中 - 我错过了什么?

标签 c# wpf user-interface

概述

我是 WPF 的新手,我有一个带有文本区域、按钮和文本 block 的简单窗口。单击按钮时,我想将文本 block 更新为“开始..”或其他内容,运行一个需要几分钟的例程,最后将其更新为“完成”。

问题:

目前我的文本 block 只更新了“完成”消息。 :(

代码:

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        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;
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        private void ScriptToFileButton_Click(object sender, RoutedEventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                for (int i = 0; i < 50; i++)
                {
                    System.Threading.Thread.Sleep(100);
                    MyValue = i.ToString();
                }
            });

            MyValue = "Scripting, please wait..";
            String text = DBObjectsTextArea.Text;
            String[] args = text.Split(' ');
            SQLScripter scripter = new SQLScripter();
            scripter.script(args);
            MyValue = "Done!";

        }
        private void Window_Closed(object sender, EventArgs e)
        {
            Application.Current.Shutdown();
        }
    }

XAML:

 <TextBox Height="109" HorizontalAlignment="Left" Margin="45,12,0,0" Name="DBObjectsTextArea" VerticalAlignment="Top" Width="418" />
        <Button Content="Script To File" Height="23" HorizontalAlignment="Left" Margin="173,145,0,0" Name="ScriptToFileButton" VerticalAlignment="Top" Width="168" Click="ScriptToFileButton_Click" />
        <TextBlock Height="56" HorizontalAlignment="Left" Margin="45,197,0,0" Name="StatusTextBlock" Text="{Binding Path=MyValue}" VerticalAlignment="Top" Width="409" />

类似链接:

我的代码基于此: How do I refresh visual control properties (TextBlock.text) set inside a loop?

最佳答案

您可以将您的事件处理程序更改为此...

   private void ScriptToFileButton_Click(object sender, RoutedEventArgs e)
        {
            String text = DBObjectsTextArea.Text;
            Task t = new Task(() => PerformOnDispatcher(() => { MyValue = "Scripting, please wait.."; }));
            ManualResetEvent mre = new ManualResetEvent(false);
            t.ContinueWith((x) =>
            {
                // scripting code goes here...
                mre.Set();
            }, TaskContinuationOptions.LongRunning);

            t.ContinueWith((y) => 
            { 
                mre.WaitOne();
                PerformOnDispatcher(() => { MyValue = "Scripting, please wait.."; });
            });
            t.Start();
        }

这将工作分为三个阶段:告诉用户脚本已经开始,然后开始工作,然后告诉用户工作已经完成。同步由“ContinueWith”方法控制。此方法会等到前一个方法完成后再开始。

因为它在任务中,所以对 UI 的更改通过调度程序编码返回,调度程序使用单独的调度程序,因此不会被阻止。

最后一条语句 t.Start() 启动事件序列,因此单击按钮的用户体验不会受到阻塞的 UI 的影响。事件处理程序几乎立即返回。

如果工作进展得非常快,您仍然可能只看到“完成”,因为之前的消息在您有机会阅读之前就被覆盖了。所以调试这些东西的最好方法是将调试器锚定在这个语句上:

PropertyChanged(this, new PropertyChangedEventArgs(propName));

这将让您观察正在通过管道传输到绑定(bind)引擎的内容。

最后,为了使事件处理程序不那么困惑,以便专注于问题,我使用了一种方便的方法...

    private void PerformOnDispatcher(Action a)
    {
        Dispatcher.InvokeAsync(a);
    }

对于工业级应用,这将是一种扩展方法或在属性 setter 中完成。

关于c# - 文本更新未反射(reflect)在 WPF TextBlock 中 - 我错过了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23810179/

相关文章:

c# - 如何将 IsEnabled 绑定(bind)到 xaml 中的 vm 属性以获取 DataTemplate 中的按钮?

WPF 菜单未正常定位

c# - 继承自 IEnumerable

php - 如何让用户打印和下载MySQL查询结果

c# - 如何在 ASP.NET 中获取节点的属性?

c# - 如何从客户端脚本访问参数

c# - TCP 客户端服务器问题

c# - 在 WebMethod 内强制回发

c# - 在 wpf 中绑定(bind) IEnumerable<IGrouping<string,BaseDto>> 类型对象

iphone - 自定义导航栏