2015-08-14 43 views
0

我有一個問題,一直在困擾着我好幾天,我試過每一個選項,現在我發佈了自己的問題,以找到你們的一些具體幫助。在MainWindow的代碼塊開始更新TextBlock異步

我需要在代碼塊的開始更新一個TextBlock,它是在一個簡單的按鈕單擊運行。

這裏是我的代碼:

private void NewProject(bool blnCopy = false, string strFileName = null) 
    { 
     if (App.ApplicationBusy == false) 
     { 
     App.ApplicationBusy = true; 

     try 
     { 
      Action action = delegate() 
      { 
      Cursor = Cursors.Wait; 
      lblStatus.Text = "Opening Project..."; 
      }; 

      Dispatcher.Invoke(DispatcherPriority.Send, action); 

      if (blnCopy == false) { Project = new GSProject((App.RecentProjectCount + 1)); } 

      if (Project != null) 
      { 
      Projects.Add(Project); 

      if (blnCopy == false) 
      { 
       if (strFileName == null) 
       { 
       Project.ProjectName = string.Format("GSProject{0}", Projects.Count.ToString()); 
       Project.ProjectDescription = string.Format("{0} - HW GS Project", Project.ProjectName); 
       Project.LoadResource(); 
       } 
       else 
       { 
       Project.Load(strFileName); 
       } 
      } 
      else 
      { 
       Project = Project.Copy(); 
      } 

      p_objNewPane = objDocker.AddDocument(Project.ProjectDisplayName, Project); 

      if (p_objNewPane != null) 
      { 
       p_objNewPane.DataContext = Project; 
       BindingOperations.SetBinding(p_objNewPane, ContentPane.HeaderProperty, new Binding("ProjectDisplayName") { Source = Project }); 
       p_objNewPane.Closing += new EventHandler<PaneClosingEventArgs>(ContentPane_Closing); 
      } 

      if (Project.CalculationExists == true) 
      { 
       InitializeCalculation(true); 
      } 
      } 
      tabStartPage.Visibility = Visibility.Collapsed; 
      objDocumentTabs.SelectedIndex = 0; 
     } 
     catch (Exception ex) 
     { 
      ModernDialog.ShowMessage(string.Format("An error has occurred:{0}{0}{1}", Environment.NewLine, ex.Message), "Error", MessageBoxButton.OK, Application.Current.MainWindow); 
     } 
     finally 
     { 
      App.ApplicationBusy = false; 
      Cursor = Cursors.Arrow; 
      AppStatus = "Ready"; 
      p_objNewPane = null; 
     } 
     } 
    } 

在try塊的開始,我需要更新的TextBlock(lblStatus)說這是怎麼回事。 void本身NewProject位於MainWindow上,並通過按鈕單擊來調用。

有人能給我一個我要去哪裏錯的想法嗎?我已經嘗試了無數的潛在解決方案,所以如果我回復你說我已經嘗試過了,請不要被冒犯。

問候,湯姆。

+0

你還沒有說過什麼問題,只是說你想更新一個TextBox ..? –

+0

對不起,問題是TextBlock根本沒有更新。它只是說「準備好」(在MainWindow的加載時設置)。 –

回答

0

經過幾天痛苦的日子,我設法讓這個工作。通過查看任務調度等,我完全吠叫了錯誤的樹。相反,所需的只是一個DependencyProperty。

XAML(主窗口):

<TextBlock x:Name="lblStatus" 
      Text="{Binding AppStatus, IsAsync=True}" 
      Grid.Column="0" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      FontFamily="Segoe UI" 
      FontSize="12" 
      Foreground="White" 
      Margin="5, 0, 0, 0" /> 

C#(主窗口):

public string AppStatus 
    { 
     get { return (string)GetValue(AppStatusProperty); } 
     set { SetValue(AppStatusProperty, value); } 
    } 
    public static readonly DependencyProperty AppStatusProperty = 
     DependencyProperty.Register("AppStatus", typeof(string), typeof(MainWindow), new PropertyMetadata(null)); 

public void StatusBarUpdate(string strMainMessage) 
    { 
     Dispatcher.BeginInvoke((Action)(() => { AppStatus = strMainMessage; })); 
    } 

我然後可以調用在任何時間StatusBarUpdate方法,它將異步更新UI。

0

您正在使用WPF,因此實現

INotifyPropertyChanged 

,並使用適當的數據綁定。

private void NotifyPropertyChanged(String info) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 
public string StatusText 
{ 
    get {return this.m_statusText;} 

    set 
    { 
     if (value != this.m_statusText) 
     { 
      this.m_statusText= value; 
      NotifyPropertyChanged("StatusText"); 
     } 
    } 
} 

而在XAML

<TextBox Text="{Binding Path=StatusText}"/> 
+0

謝謝曼紐爾 - 這是我原來的設置,如果沒有這個,我將它改爲簡單的lblStatus.Text,看看它是否有所作爲。 最初我有一個名爲AppStatus的INPC字符串,TextBlock被綁定到上面,然後我只需調用AppStatus =「打開項目」。不幸的是,結果與現在一樣。 –

+0

好的,但數據綁定是如何做到這一點的正確方法。我會試着讓這種方法奏效。 您是否設置了DataContext? 您可以在VisualStudio中啓用WPF綁定錯誤消息 –

+0

謝謝我會讓你知道我如何繼續! –

0

您沒有提及究竟是什麼的問題,而是看代碼,我可以猜測,該文本框顯示「打開項目...」只完成後您的代碼或顯示「就緒」,如果AppStatus正在做同樣的事情。

如果是的話,問題是你正在UI線程上做所有事情。雖然您更改了文本框的文本,但是在完成工作後將會呈現它,因此會出現問題。要解決此問題,您需要在工作線程上運行代碼if (blnCopy == false)objDocumentTabs.SelectedIndex = 0;。這將解決您的問題。

您可以使用TPL,也可以使用.ContinueWithTaskScheduler.FromCurrentSynchronizationContextTaskContinuationOptions.OnlyOnRanToCompletion來執行finally塊。

編輯: 由於您不使用MVVM,您需要很多Invoke才能使您的代碼正常工作。正如我所看到的,p_objNewPane也是一個UI元素,就像Project是一個視圖屬性,它將很難翻譯所有的TPL。您可以保留p_objNewPane = ...的代碼(即外部工作線程)。這似乎不是很密集的cpu,除了可以在另一個工作線程中運行的InitializeCalculation

更好的方法是使用await/async方法來等待所有繁重的提升方法。

+0

感謝Yogesh - 是的你是正確的,TextBlock不會更新,直到結束。我的問題是,「項目」是一個依賴項屬性,所以使用例如BackgroundWorker或await Task.Run()會導致異常,因爲我無法訪問UI線程之外的propdp。 –

+0

而不是直接分配或修改依賴項屬性,只需創建一個新的「項目」實例並返回此實例作爲任務結果。在'ContinueWith'方法中,只需將您的依賴項屬性分配給返回的'Project'實例。 – Yogesh