WPF:dispatcher.invoke 不 运行
WPF: dispatcher.invoke do not running
我写了我的第一个 WPF 应用程序,它包含几个页面:
- 带有一些徽标的欢迎页面
- 登录页面 带有登录表单
- 主页 包含帐户信息
MainWindow 包含 <Frame>
WPF 控件,我使用动画显示 next/previous 页面。
我自己写MainAnimation
class来执行动画
这个应用程序在我的笔记本电脑上运行良好,但是当我尝试运行它在我朋友动画的机器上时,它什么也没做。
我认为这个问题与 Dispatcher.Invoke()
方法调用有关,我试图通过网络 (here here here and here) 找到解决方案,我尝试了:
- 使用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
class 上的相关部分 (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 用于开发:Windows 10 x64
- OS 用于测试:Windows 8.1 x64
- VS版本:Visual Studio2017社区版
- 应用程序目标框架:v.4.5
由于 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
。
我写了我的第一个 WPF 应用程序,它包含几个页面:
- 带有一些徽标的欢迎页面
- 登录页面 带有登录表单
- 主页 包含帐户信息
MainWindow 包含 <Frame>
WPF 控件,我使用动画显示 next/previous 页面。
我自己写MainAnimation
class来执行动画
这个应用程序在我的笔记本电脑上运行良好,但是当我尝试运行它在我朋友动画的机器上时,它什么也没做。
我认为这个问题与 Dispatcher.Invoke()
方法调用有关,我试图通过网络 (here here here and here) 找到解决方案,我尝试了:
- 使用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
class 上的相关部分 (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 用于开发:Windows 10 x64
- OS 用于测试:Windows 8.1 x64
- VS版本:Visual Studio2017社区版
- 应用程序目标框架:v.4.5
由于 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
。