2013-10-02 131 views
0

我有一個'加載數據'進程,可能需要1到20秒的任何地方,所以我想在我的窗口上顯示一個狀態消息。我的窗口網格有一行,根據綁定到我的視圖模型的觸發器將會顯示或隱藏一行。這很好。我的問題是我如何改變綁定,並獲得用戶界面刷新之前我長時間運行的任務開始。現在發生的情況是Status屬性已設置,然後我開始執行我的任務,但直到我的任務完成後才刷新UI。這是我的xaml和視圖模型代碼。WPF MVVM綁定刷新顯示狀態

<Grid Grid.Row="4" Background="{StaticResource appPrimaryBackColorLight}" Height="20"> 
    <Grid.Style> 
     <Style TargetType="Grid"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding StatusMessageVisibility}" Value="Collapsed"> 
        <DataTrigger.EnterActions> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Storyboard.TargetProperty="Height" From="20" To="0" Duration="0:0:0.1" /> 
          </Storyboard> 
         </BeginStoryboard> 
        </DataTrigger.EnterActions> 
        <DataTrigger.ExitActions> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Storyboard.TargetProperty="Height" From="0" To="20" Duration="0:0:.1" /> 
          </Storyboard> 
         </BeginStoryboard> 
        </DataTrigger.ExitActions> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Grid.Style> 
    <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> 
     <Image Width="20" Height="20" Grid.RowSpan="2" ani:ImageBehavior.AnimatedSource="/Images/spinner_status_20.gif"></Image> 
     <TextBlock Text="{Binding StatusMessage}" Height="20" VerticalAlignment="Center" Padding="5,1,0,0" Style="{StaticResource appTextBlockSmallDark}" Foreground="White" /> 
    </StackPanel> 
</Grid> 


private void LoadImportData() 
{ 
    // Show the status message by changing the view model properties 
    StatusMessage = "Loading data from import file. Please stand by..."; 
    StatusMessageVisibility = Visibility.Visible; 

    Task.Factory.StartNew(() => 
          { 
           //This invokes UI specific code inside module initialization 
           LoadDataNow(); 
          }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext()); 
} 
+0

「StatusMessage」和「StatusMessageVisibility」的設置看起來像什麼?兩個都實現了INotifyPropertyChanged嗎? – Jay

+0

是的......我正在使用MVVM Light併爲每個調用RaisePropertyChanged(),以便通知視圖。 – Mikkeee

回答

2

問題是您正在爲您的任務使用當前同步上下文 - 即UI線程。你沒有在後臺線程上運行它。相反,使用您的工作任務的默認參數將其安排在單獨的線程上,並創建一個在UI線程上運行的延續。此任務將在任務完成後更新UI。

var task = Task.Factory.StartNew(() => 
         { 
          //This invokes UI specific code inside module initialization 
          LoadDataNow(); 
         }); 
task.ContinueWith(t => StatusMessageVisibility = Visibility.None, 
         TaskScheduler.FromCurrentSynchronizationContext()); 
+0

所以這是我的問題。我的LoadDataNow方法從文件中獲取數據並將其加載到DevExpress GridControl中。不幸的是,即使我沒有將這個網格放置在Window上,網格需要在UI線程上運行,或者我得到錯誤「調用線程必須是STA,因爲很多UI組件都需要這個。」 我來自.NET 2.0世界,希望更好地理解和利用TPL。我知道我可以使用後臺工作人員來執行此操作,但使用任務看起來會更清晰。 – Mikkeee

+1

將後臺任務中的所有數據加載到內存中(這應該是長時間運行的位),然後將其綁定到網格控件的後續部分。您不能也不應該將長時間運行的流程與UI代碼混合在一起。 –

+0

感謝蒂姆,但不幸的是,這不是一個選項,因爲網格交互是我長時間運行過程中不可或缺的一部分。這是我在做什麼: (1)將一個大的Excel工作簿加載到數據表中 (2)將數據表分配給devexpress網格。 (3)針對網格中的數據運行大量文件管理器(DevExpress網格在高級過濾和性能之間,這是我使用它的原因)。 (4)將剩餘的過濾數據保存到我的數據庫中。 – Mikkeee