2014-10-17 67 views
0

我正在玩WPF。我僅限於.Net框架3.5。我想用簡單的狀態文本更新文本框,同時運行一些較長的方法。無論我嘗試什麼,在長方法完成之前,我似乎都無法獲得更新文本框。我已經嘗試了線程/使用控件調度器等。在下面的例子中,我已經回到簡單地將長方法解決給線程,但它仍然不會工作。在長方法(LoadDevices)完成之前,TextStatus文本框永遠不會更新。有人能告訴我如何做到這一點?任何幫助非常感謝。WPF,我如何強制更新文本框

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

「TextStatus」是否綁定到您的文本框?它是一個DependencyProperty? – PoweredByOrange 2014-10-17 16:32:44

+1

*看起來似乎應該起作用,儘管利用綁定會更好。 – BradleyDotNET 2014-10-17 16:33:06

+1

請注意,使用WPF時,最好使用MVVM模式。使許多事情變得更容易等 – walther 2014-10-17 16:43:42

回答

0

如果你還沒有嘗試的代表,這可能是你在找什麼,雖然看來你可能已經嘗試過了。在您的LoadDevices線程方法內部,您可以使用您的long方法運行時所需的任何文本代替以調用UpdateStatus。

另一種情況下,我看到您的問題的措辭是本地的方法更新狀態嘗試通過調用來更改文本。但是,它不能出於某種原因。

這可能是compleatly無關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 }); 
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,數據綁定,命令等。並儘量避免填充邏輯代碼隱藏。

+0

這裏沒有數據綁定。我只想用狀態字符串更新文本框。我不想用LoadDevices來做這件事,因爲除了它我還想更新狀態之外,還有其他方法。所以我設想了一種方法,在每次調用之前調用各種長方法,我更新狀態。 – user2026382 2014-10-17 17:59:25

+0

@ user2026382但不管從LoadDevices更新,它都應該是數據綁定的。我會接受這個建議。 – BradleyDotNET 2014-10-17 18:00:30

+0

沒有數據綁定,但更新Text屬性是綁定'''的基本場景。這將照顧沒有明確附加文本的更新。 – 2014-10-17 18:02:10