WPF,如何强制文本框更新

时间:2014-10-17 16:29:21

标签: c# wpf .net-3.5

我正在玩WPF。我仅限于.Net framework 3.5。我想在运行一些长方法时用简单的状态文本更新文本框。无论我尝试什么,在长方法完成之前,我似乎无法更新文本框。我已经尝试过线程/使用控件调度程序等。在下面的例子中,我已经恢复为简单地将长方法移植到线程但它仍然无法工作。 TextStatus文本框永远不会更新,直到long方法(LoadDevices)完成。谁能告诉我怎么做?任何帮助非常感谢。

    private void UpdateButton_Click(object sender, RoutedEventArgs e)
    {
        UpdateStatus("Searching for devices, please wait . . .");
        var t = new Thread(LoadDevices);
        t.Start();            
    }

    private void UpdateStatus(string status)
    {
        TextStatus.AppendText(status);
        TextStatus.InvalidateVisual();
    }

3 个答案:

答案 0 :(得分:1)

我认为您没有提供足够的代码来解决问题。但事实是,您的用户界面已被阻止。

尝试以下操作,也许它可以帮助您解决问题(不使用Task,因为它.NET Framework 3.5中不可用)。它会尝试模拟您长时间运行的LoadDevices()方法,同时保持UI响应。

<强> MainWindows.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Height="120"
        Width="400">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Button Click="UpdateButtonClick" Grid.Row="0">Update</Button>
        <TextBox Name="TextStatus" Text="" TextWrapping="Wrap" Grid.Row="1"></TextBox>
    </Grid>
</Window>

<强> MainWindows.xaml.cs

using System;
using System.Threading;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void UpdateButtonClick(object sender, RoutedEventArgs e)
        {
            UpdateStatus("Searching for devices, please wait");
            var thread = new Thread(LoadDevices);
            thread.Start();
        }

        private void LoadDevices()
        {
            // Your long running "load devices" implementation goes here
            for (int i = 0; i < 15; i++)
            {
                Dispatcher.BeginInvoke((Action) (() => UpdateStatus(".")));
                Thread.Sleep(250);
            }
            Dispatcher.BeginInvoke((Action)(() => UpdateStatus(" done")));
        }

        private void UpdateStatus(string status)
        {
            TextStatus.AppendText(status);
        }
    }
}

enter image description here

但是,你应该更喜欢MVVM,数据绑定,命令等,并尽量避免将逻辑填充到代码隐藏中。

答案 1 :(得分:0)

尝试使用任务库。您需要为.NET 3.5下载此代码:http://www.microsoft.com/en-us/download/details.aspx?id=24940

Task task = new Task(new Action(LoadDevices));
task.Start();

有几种方法可以做到这一点: http://dotnetcodr.com/2014/01/01/5-ways-to-start-a-task-in-net-c/

答案 2 :(得分:0)

如果您还没有尝试过代表,那可能就是您正在寻找的内容,尽管您似乎已经尝试过了。在您的LoadDevices线程方法中,您可以委托回调用UpdateStatus,并在您运行long方法时使用您想要的任何文本。

我在问题的措辞中看到的另一种情况是方法的本地化更新状态试图通过调用来更改文本。但是,它不能出于某种原因。

这可能与WPF完全无关,但在表格中:

我假设你在其他地方有你的加载线程。我没有看到你在线程中调用doWork()或等效方法。如果要在加载线程加载设备时更新状态,可以执行以下操作:

    private delegate void UpdateStatusDel(string text); //This at your declarations
    UpdateStatusHandler = new UpdateStatusDel(UpdateStatus); //To initialize the delegate to /       //point to your update textbox function
    //say you have  
    string updateText = "Loading 10% done";
    //Then, in your thread you could invoke
    [locationOfHandeler].Invoke(UpdateStatusHandler, new object[] { updateText });