WPF:dispatcher.invoke没有运行

时间:2017-08-09 09:44:55

标签: c# wpf xaml dispatcher

我编写了第一个WPF应用程序,它包含几个页面:

  1. 欢迎页面,带有一些徽标
  2. 使用登录表单
  3. 登录页面
  4. 主页,包含帐户信息
  5. MainWindow包含<Frame> WPF控件,我使用动画显示下一页/上一页。

    我编写自己的MainAnimation类来执行动画。

    这个应用程序在我的笔记本电脑上工作正常,但是当我尝试在我朋友动画的机器上运行它时什么都不做。

    我认为与Dispatcher.Invoke()方法调用相关的麻烦,我尝试通过网络找到解决方案(here here herehere)和我试过了:

    • 使用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:软件版本

    • 用于开发的操作系统:Windows 10 x64
    • 测试操作系统:Windows 8.1 x64
    • VS版:Visual Studio 2017社区版
    • 应用程序目标框架:v.4.5

1 个答案:

答案 0 :(得分: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