如何制作一个同时执行两个操作的良好启动画面?
How can I make a good splash screen that does two actions at once?
我目前正在尝试制作启动画面,但是,我似乎无法同时完成一些任务设置。
我试过使用 BackgroundWorker
class,以及 Thread
class,none 似乎有效。
在App.xaml.cs中:
protected override void OnStartup(StartupEventArgs e)
{
var splashScreen = new Windows.Splash();
splashScreen.Show();
base.OnStartup(e);
splashScreen.Close();
}
在splashScreen.xaml.cs中:
public Splash()
{
InitializeComponent();
DataContext = this;
changeLoadingTxtTimer = new System.Timers.Timer(2000);
changeLoadingTxtTimer.Elapsed += Timer_Elapsed;
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += D_DoWork;
backgroundWorker.RunWorkerAsync();
changeLoadingTxtTimer.Start();
}
private void D_DoWork(object sender, DoWorkEventArgs e) { UpdateDatabase(); }
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
LoadingTxtValue = LoadingTxts[rd.Next(0, LoadingTxts.Length - 1)];
if (!backgroundWorker.IsBusy)
changeLoadingTxtTimer.Stop();
}
}
我预计 BackgroundWorker
工作时,加载文本将每 2 秒更改一次,但实际发生的是 BackgroundWorker
完成其工作,启动画面关闭。
如果我没理解错的话,你有一个字符串列表:
var TextList = new[] {"Text 1", "Text 2", "Text 3"};
当后台作业正在进行时,您希望这些字符串每 2 秒出现一次。
我不知道你的后台工作人员做了什么,但我假设你知道你在用它做什么。
我还假设您的 Textblock
在您的控件上绑定到名为 LoadingTxtValue
的字符串 属性。
我认为这项工作的最佳工具是 Reactive。添加对 System.Reactive 的引用,并在 RunWorkerAsync
之后使用以下内容。
Observable.Timer(TimeSpan.FromSeconds(2))
.Subscribe(
t => App.Current.Dispatcher.Invoke(new Action(() => LoadingTxtValue = TextList[t])));
希望能解决您的问题
我认为您应该在主视图本身内部对主视图进行初始化。一旦主视图被初始化,它就会引发一个相应的事件。然后,您通过关闭初始屏幕并显示主视图来对此事件作出反应。所以启动画面的唯一任务就是显示启动内容。
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.splashScreen = new Windows.Splash();
this.splashScreen.Show();
// Initialize the main application view
this.MainWindow = new MainWindow();
this.MainWindow.Initialized += ShowMainWindow;
this.MainWindow.Initialize();
}
private void ShowMainWindow(object sender, EventArgs e)
{
this.splashScreen.CloseSplashScreen();
this.MainWindow.Show();
}
Splash.xaml.cs:
public Splash()
{
InitializeComponent();
this.DataContext = this;
this.changeLoadingTxtTimer = new System.Timers.Timer(2000);
this.changeLoadingTxtTimer.Elapsed += Timer_Elapsed;
this.changeLoadingTxtTimer.Start();
}
public void CloseSplashScreen()
{
this.changeLoadingTxtTimer.Stop();
this.changeLoadingTxtTimer.Dispose();
Close();
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.Dispatcher.Invoke(() => this.LoadingTxtValue = this.LoadingTxts[rd.Next(0, this.LoadingTxts.Length - 1)]);
}
App.xaml
删除 StartupUri
条目
<Application
x:Class="WpfSplashApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfSplashApp">
<Application.Resources />
</Application>
App.xaml.cs
public partial class App : Application
{
public App()
{
Startup += App_Startup;
}
private async void App_Startup( object sender, StartupEventArgs e )
{
var splash = new SplashWindow();
splash.Show();
await InitializeAsync();
var main = new MainWindow();
main.Show();
MainWindow = main;
splash.Close();
}
private Task InitializeAsync()
{
// Do some ASYNC initialization
return Task.Delay( 5000 );
}
}
我目前正在尝试制作启动画面,但是,我似乎无法同时完成一些任务设置。
我试过使用 BackgroundWorker
class,以及 Thread
class,none 似乎有效。
在App.xaml.cs中:
protected override void OnStartup(StartupEventArgs e)
{
var splashScreen = new Windows.Splash();
splashScreen.Show();
base.OnStartup(e);
splashScreen.Close();
}
在splashScreen.xaml.cs中:
public Splash()
{
InitializeComponent();
DataContext = this;
changeLoadingTxtTimer = new System.Timers.Timer(2000);
changeLoadingTxtTimer.Elapsed += Timer_Elapsed;
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += D_DoWork;
backgroundWorker.RunWorkerAsync();
changeLoadingTxtTimer.Start();
}
private void D_DoWork(object sender, DoWorkEventArgs e) { UpdateDatabase(); }
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
LoadingTxtValue = LoadingTxts[rd.Next(0, LoadingTxts.Length - 1)];
if (!backgroundWorker.IsBusy)
changeLoadingTxtTimer.Stop();
}
}
我预计 BackgroundWorker
工作时,加载文本将每 2 秒更改一次,但实际发生的是 BackgroundWorker
完成其工作,启动画面关闭。
如果我没理解错的话,你有一个字符串列表:
var TextList = new[] {"Text 1", "Text 2", "Text 3"};
当后台作业正在进行时,您希望这些字符串每 2 秒出现一次。
我不知道你的后台工作人员做了什么,但我假设你知道你在用它做什么。
我还假设您的 Textblock
在您的控件上绑定到名为 LoadingTxtValue
的字符串 属性。
我认为这项工作的最佳工具是 Reactive。添加对 System.Reactive 的引用,并在 RunWorkerAsync
之后使用以下内容。
Observable.Timer(TimeSpan.FromSeconds(2))
.Subscribe(
t => App.Current.Dispatcher.Invoke(new Action(() => LoadingTxtValue = TextList[t])));
希望能解决您的问题
我认为您应该在主视图本身内部对主视图进行初始化。一旦主视图被初始化,它就会引发一个相应的事件。然后,您通过关闭初始屏幕并显示主视图来对此事件作出反应。所以启动画面的唯一任务就是显示启动内容。
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.splashScreen = new Windows.Splash();
this.splashScreen.Show();
// Initialize the main application view
this.MainWindow = new MainWindow();
this.MainWindow.Initialized += ShowMainWindow;
this.MainWindow.Initialize();
}
private void ShowMainWindow(object sender, EventArgs e)
{
this.splashScreen.CloseSplashScreen();
this.MainWindow.Show();
}
Splash.xaml.cs:
public Splash()
{
InitializeComponent();
this.DataContext = this;
this.changeLoadingTxtTimer = new System.Timers.Timer(2000);
this.changeLoadingTxtTimer.Elapsed += Timer_Elapsed;
this.changeLoadingTxtTimer.Start();
}
public void CloseSplashScreen()
{
this.changeLoadingTxtTimer.Stop();
this.changeLoadingTxtTimer.Dispose();
Close();
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.Dispatcher.Invoke(() => this.LoadingTxtValue = this.LoadingTxts[rd.Next(0, this.LoadingTxts.Length - 1)]);
}
App.xaml
删除 StartupUri
条目
<Application
x:Class="WpfSplashApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfSplashApp">
<Application.Resources />
</Application>
App.xaml.cs
public partial class App : Application
{
public App()
{
Startup += App_Startup;
}
private async void App_Startup( object sender, StartupEventArgs e )
{
var splash = new SplashWindow();
splash.Show();
await InitializeAsync();
var main = new MainWindow();
main.Show();
MainWindow = main;
splash.Close();
}
private Task InitializeAsync()
{
// Do some ASYNC initialization
return Task.Delay( 5000 );
}
}