2016-02-01 64 views
0

嗨我試圖在某些耗時的操作執行中顯示GIf圖像。在WPF中無法顯示GIF加載器執行數據庫操作時

我試着用下面的代碼..我能夠看到加載窗口,但gif圖像的動畫不工作..當搜索解決方案時,我發現方法來更新用戶界面,而其凍結的背景功能。但它仍然不起作用。這裏是我的裝載機窗口XAML代碼:

<Window x:Class="project1.Views.loader" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 
    xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
    xmlns:gif="http://wpfanimatedgif.codeplex.com" 
    gif:ImageBehavior.AnimateInDesignMode="True" 
    Title="Loading" Height="180" Width="461" WindowStartupLocation="CenterScreen" ResizeMode="NoResize" WindowStyle="SingleBorderWindow" Loaded="Window_Loaded"> 
<StackPanel Name="LoadingData" Background="White" > 
    <Label x:Name="lblprogressmessage" x:FieldModifier="public" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,35,0,10" Content="" Foreground="#FF1E8ED4" FontSize="14"></Label> 
    <Image x:Name="imggif" gif:ImageBehavior.RepeatBehavior="Forever" gif:ImageBehavior.AnimatedSource="pack://application:,,,/project1;component/Images/ajaxloader.gif" Height="50px" Width="60px"/> 
</StackPanel> 
</Window> 

想顯示其中有按鈕,將在這裏做的點擊時有些DB操作另一用戶控制窗口這個窗口是我的按鈕代碼

loaderWindow ld = new loaderWindow // object to show loader window 
Sample ViewModel = new Sample(); 

private void btn_Click(object sender, RoutedEventArgs e) 
{ 
    try 
    {   
     SampleEntityManager objem = new SampleEntityManager(); 
     using (var dbContext = Database1.getDBContext()) 
     { 
     if(objem .checkFundExist(dbContext,Guid.Parse(cbx1SelectedValue.ToString()), Guid.Parse(cbx2.SelectedValue.ToString()), int.Parse(cbx3.SelectedValue.ToString())) == false) 
      { 
      BackgroundWorker bw = new BackgroundWorker(); 
      bw.WorkerSupportsCancellation = true; 
      bw.WorkerReportsProgress = true; 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
      ForceUIToUpdate(); 
      bw.RunWorkerAsync(); 
      ld.lblprogressmessage.Content = "Creating Fund for Year "+cbx1.Text +" Please Wait. . ."; 

      *ld.Show();* // calling show method to display loader window 
      } 
     else 
      { 
      MessageBox.Show("Fund Has Already Been Created", "Info", MessageBoxButton.OK, MessageBoxImage.Information); 
      } 
     } 
     }  
     catch (Exception es) 
     { 
     MessageBox.Show("Invalid Opertaion try again.If Problem Persists Contact Support", "Error", MessageBoxButton.OK, MessageBoxImage.Information); 
     } 
} 

這裏是方法來強制更新上凍結

// method to update UI 
    public static void ForceUIToUpdate() 
    { 
     DispatcherFrame frame = new DispatcherFrame(); 

     Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate (object parameter) 
     { 
      frame.Continue = false; 
      return null; 
     }), null); 

     Dispatcher.PushFrame(frame); 
    } 

而且後臺工作的代碼UI如下

private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 
     if ((worker.CancellationPending == true)) 
     { 
      e.Cancel = true; 
     } 
     else 
     { 
      // Perform a time consuming operation and report progress. 

      this.Dispatcher.InvokeAsync((Action)(() => 
      { 
       // Time Consuming Database method which will set Fund entry Field for all the employess in Union 
       ViewModel .CreateFund(cbx1.SelectedItem, cbx2.SelectedItem,cbx3.SelectedValue.ToString(), txt_desc.Text); 
       cbx1.SelectedIndex = -1; 
       cbx2.SelectedIndex = -1; 
       **ld.Hide();** // calling Hide Method close Loader window once database opertaion completed 
      }), System.Windows.Threading.DispatcherPriority.Background); 
     } 
    } 

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     BackgroundWorker worker = (BackgroundWorker)sender; 
     if ((e.Cancelled == true)) 
     { 
      ld.lblprogressmessage.Content = "Cancelled !"; 
     } 
     else if (!(e.Error == null)) 
     { 
      ld.lblprogressmessage.Content = ("Error : " + e.Error.Message); 
     } 
     else 
     { 
      if (worker.WorkerSupportsCancellation == true) 
      { 
       worker.CancelAsync(); 
      } 
     } 
    } 

請建議我的方式來完成我的任務。謝謝

回答

1

您正在使用BackgroundWorker錯誤。您從DoWork方法調用Dispatcher.InvokeAsync,該方法實際上是在UI線程上執行代碼,而不是後臺線程,因此阻止了UI。您需要做的是找到一種方法在後臺實際執行耗時的代碼,然後在工作完成時僅從RunWorkerCompleted更新UI,如果需要在執行過程中更新UI,則可以使用ReportProgress

How to: Use a Background Worker

此外,顯示當你開始工人,像你已經做了裝載機窗口,但調用該方法從RunWorkerCompleted,這是在UI線程上執行後的研究背景線程是隱藏完成後,不是從DoWork的方法。

+0

嗨@Nemanja Banda我嘗試刪除Dispatcher.invokeAsync,但它顯示此錯誤「調用線程不能訪問此對象,因爲不同的線程擁有它。在ViewModel .CreateFund()行..是否有任何其他方式使其在後臺運行 –

+1

您試圖從後臺線程,這是不允許在WPF中訪問UI對象。你可以做的是創建一個類,它將保存所有的信息,用你需要的用戶界面的數據填充它,然後將它傳遞給'BackgroudWorker'來完成數據的所有工作,而無需訪問UI ... –

+0

謝謝@Nemanja Banda我嘗試創建另一個類來接受輸入和工作.. –

相關問題