2017-08-09 99 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。 –