WPF TextBox不会从有界类更新

时间:2018-02-02 13:57:20

标签: c# wpf xaml textbox

当目前任何班级更改文本时,我目前仍然坚持如何更新文本框的文本。目前,只有我的主线程这样做,并且我尝试了各种方法(包括调度)来从任何地方更新视图。我的代码如下所示:

XAML:

<TextBox x:Name ="textBoxResults" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>

XAML.CS:

public partial class MainWindow : Window
    {
        public ConsoleLog cl { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            MainWindow_Load();
            cl = new ConsoleLog();
            DataContext = cl;
        }
}
    private void ButtonBeginTests_Click(object sender, RoutedEventArgs e)
    {

        new Thread(() =>
        {
        App.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new Action(() =>{
            tc = new TestController(.., .., cl); //other args not important
            tc.beginTest();
        }));
        }).Start();
    }

ConsoleLog类:

using System;
using System.ComponentModel;

namespace Test_DesktopApplication.src
{
    public class ConsoleLog : INotifyPropertyChanged
    {

        private string text;
        public string Text
        {
            get { return text; }
            set
            {
                text = value;
                OnPropertyChanged("Text");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public void addToLog(string text)
        {
            App.Current.Dispatcher.Invoke(new Action(delegate { this.Text += text; }));
        }
}

一个类在后台进程的单独线程中多次调用“addToLog”。我可能做错什么的任何迹象?

编辑:我可以实际上通过在每次addToLog调用之后使用它来使其工作:

App.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new ThreadStart(delegate { }));

然而,我不知道这是否是一个“好”的修复。

编辑2:

我已更新MainWindow类以显示何时调用此类,调用日志的类如下:

public class Testcontroller
{

ConsoleLog cl;

public GEN2TestController(.., .., ConsoleLog console)
{
    //other constructor things
    cl = console;
}
public void beginTest(){
    testList[0].result = unprogrammedCurrent_test(.., ..); //this is an example of what the test looks like..
    cl.addToLog(TestList[0].result);
    ...//repeat for the rest of the test lists and tests..
    ...
    ...
}

在完成所有测试之前,日志不会更新。

1 个答案:

答案 0 :(得分:1)

你的代码示例工作正常!

  编辑:应该没有必要像这样强制一个空的调度程序循环,这相当于旧的WinForms Application.DoEvents()你的代码中必须有其他东西阻塞在调度程序(UI线程)中,您可能应该分享一个如何构造和启动后台工作程序的示例。

我在表单中添加了一个按钮:

<Button Margin="0,267,376,0" Click="Button_Click" Height="54" VerticalAlignment="Top" HorizontalAlignment="Right" Width="142"/>

按钮点击后面代码中的逻辑:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        cl.addToLog(DateTime.Now.ToString() + Environment.NewLine);
    }

Runtime Capture 1

  

我怀疑你发出的是你如何调用addToLog()很可能你正在调用一个不同的对象实例来设置为数据上下文。

我已修改您的示例以包含从表单启动的后台工作程序,这非常有效:

public partial class MainWindow : Window
{
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (worker.IsBusy)
            worker.CancelAsync();
        else
        {
            cl.Text = String.Empty;
            worker.RunWorkerAsync();
        }
    }
    public ConsoleLog cl { get; set; }
    private BackgroundWorker worker = null;

    public MainWindow()
    {
        InitializeComponent();
        cl = new ConsoleLog();
        DataContext = cl;
        worker = new BackgroundWorker { WorkerSupportsCancellation = true };
        worker.DoWork += Worker_DoWork;
        worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) => cl.addToLog($"{e.Result}");
    }

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Random r = new Random();
        while(true)
        {
            if ((sender as BackgroundWorker).CancellationPending) break;
            cl.addToLog(DateTime.Now.ToString() + Environment.NewLine);
            System.Threading.Thread.Sleep(r.Next(500, 3000));
        }
        e.Result = "Stop" + Environment.NewLine;
    }
}

Background worker output