2017-08-09 95 views
0

我寫我的第一個WPF應用程序,其中包括幾個頁面:WPF:dispatcher.invoke不運行

  1. 歡迎頁面一些標誌
  2. 登錄頁面與登錄表單
  3. 帶帳號信息的主頁

MainWindow包含<Frame> WPF控件和我使用動畫顯示下一頁/上一頁。

我寫我自己的MainAnimation類來執行動畫。

此應用程序在我的筆記本電腦上正常工作,但是當我嘗試在我的朋友動畫的機器上運行它時,什麼都不做。

我覺得麻煩Dispatcher.Invoke()方法調用相關的,我試圖找到解決方案通過網絡(herehereherehere),我嘗試:

  • 使用Application.Current.Dispatcher
  • 使用Dispatcher.BeginInvoke()代替Dispatcher.Invoke()

但它什麼都不做。

所以,我顯示歡迎頁面只有2秒,登錄頁面必須自動加載。

這是WelcomePage.xaml.cs文件中的代碼:

public partial class WelcomePage : Page { 
    public WelcomePage (MainWindow parent) { 
     InitializeComponent(); 
     this.parent = parent; 

     Task.Factory.StartNew(() => ShowLoginForm()); 
    } 

    private MainWindow parent; 

    private void ShowLoginForm() 
    { 
     Thread.Sleep(2000); 
     this.parent.GoToLoginForm(); 
    } 

} 

這是MainWindow.xaml.cs文件中的代碼:

public partial class MainWindow : Window { 
    public MainWindow() { 
     InitializeComponent(); 

     animation = new MainAnimation(this, this, Main, new WelcomePage(this)); 
    } 

    private MainAnimation animation; 

    public void GoToLoginForm() => animation.ShowNextPage(new LoginPage(this)); 
    public void GoToVideosForm() => animation.ShowNextPage(new MainPage(this)); 

} 

這關係零件MainAnimation類(MainAnimation.cs):

public class MainAnimation 
{ 
    public MainAnimation(FrameworkElement resourcesOwner, DispatcherObject dispatcherOwner, Frame currentPageContainer, Page firstPage) 
    { 
     this.resourcesOwner = resourcesOwner; 
     this.dispatcherOwner = dispatcherOwner; 
     this.currentPageContainer = currentPageContainer; 

     pages = new Stack<Page>(); 
     pages.Push(firstPage); 

     currentPageContainer.Content = pages.Peek(); 
    } 

    private Stack<Page> pages; 
    private FrameworkElement resourcesOwner; 
    private DispatcherObject dispatcherOwner; 
    private Frame currentPageContainer; 

    private void ShowPageForward() 
    { 
     dispatcherOwner.Dispatcher.Invoke((Action)delegate { 
      if (currentPageContainer.Content != null) 
      { 
       var page = currentPageContainer.Content as Page; 
       if (page != null) 
       { 
        page.Loaded -= NextPage_Loaded; 
        UnloadPageForward(page); 
       } 
      } 
      else 
      { 
       LoadPageForward(); 
      } 
     }); 
    } 

    private void UnloadPageForward(Page page) 
    { 
     Storyboard sb = (resourcesOwner.FindResource("SlideForwardOut") as Storyboard).Clone(); 
     sb.Completed += StoryboardForward_Completed; 
     sb.Begin(currentPageContainer); 
    } 

    private void StoryboardForward_Completed(object sender, EventArgs e) 
    { 
     LoadPageForward(); 
    } 

    private void LoadPageForward() 
    { 
     pages.Peek().Loaded += NextPage_Loaded; 
     currentPageContainer.Content = pages.Peek(); 
    } 

    private void NextPage_Loaded(object sender, RoutedEventArgs e) 
    { 
     Storyboard sb = resourcesOwner.FindResource("SlideForwardIn") as Storyboard; 
     sb.Begin(currentPageContainer); 
    } 

} 

我是新來的WPF,可能只是不明白一些細節,所以如果你能幫我解決這個小問題但是非常討厭的話,我會很高興的。

更新#1:軟件版本

  • OS的開發:視窗10 64
  • OS測試:Windows 8.1中的x64
  • VS版本:Visual Studio的2017年社區版
  • 應用目標框架:v.4。5
+1

爲什麼要在後臺線程上調用ShowLoginForm? WPF控件具有線程關聯。你爲什麼要睡覺? – mm8

+0

我認爲如果我不在後臺線程上調用ShowLoginForm,應用程序看起來像「不響應」。但我怎麼能做另一種方式? –

+0

如果你只是刪除Task.Factory.StartNew和Thread.Sleep? – mm8

回答

2

由於WPF控件具有線程相似性,因此在大多數情況下在後臺線程上創建它們沒有多大意義。

如果要等待2秒鐘,然後顯示在登錄頁面之前,你既可以使用一個DispatcherTimer或異步等待:

public partial class WelcomePage : Page 
{ 
    public WelcomePage(MainWindow parent) 
    { 
     InitializeComponent(); 
     this.parent = parent; 

     ShowLoginForm(); 
    } 

    private MainWindow parent; 

    private async void ShowLoginForm() 
    { 
     await Task.Delay(2000); 
     this.parent.GoToLoginForm(); 
    } 
} 

這樣你就不會需要Dispatcher.Invoke任何電話。

+0

感謝您的建議:我試圖在我的應用程序中使用DispatcherTimer,但是我在類LoginPage的構造函數中得到了'System.Windows.Markup.XamlParseException',並且我認爲發生這種異常是因爲我創建了'new LoginPage(this) '(在'MainWindow.GoToLoginForm()'方法內部))不是來自STA線程(而是來自爲'DispatcherTimer_Tick()'創建的線程) –

+0

DispatcherTimer_Tick在UI線程上觸發。那麼我發佈的示例代碼如何?後臺線程這裏 – mm8

+0

另外'System.Windows.Markup.XamlParseException',但另一個堆棧跟蹤。注意,異常拋出只在測試的操作系統。如果我在我的筆記本電腦上運行此應用程序它工作正常。也許它幫助。 stack trace。 –