我在c#4.0中开发一个WPF桌面应用程序,它必须处理许多长时间运行的操作(从数据库加载数据,计算模拟,优化路由等)。
当这些长时间运行的操作在后台运行时,我想显示一个Please-Wait对话框。当显示Please-Wait对话框时,应该锁定应用程序,但只是禁用应用程序窗口并不是一个好主意,因为所有DataGrids都会丢失其状态(SelectedItem
)。
到目前为止,我的工作方式有些问题: 使用Create-factory方法创建新的WaitXUI。 Create方法需要标题文本和对应该锁定的主机控件的引用。 Create方法设置窗口的StartupLocation,标题文本和要锁定的主机:
WaitXUI wait = WaitXUI.Create("Simulation running...", this);
wait.ShowDialog(new Action(() =>
{
// long running operation
}));
使用重载的ShowDialog方法,可以显示WaitXUI。 ShowDialog重载确实需要一个包装长时间运行操作的Action。
在过载的ShowDialog我刚开始动作在它自己的线程,然后禁用主机控制(设定不透明度为0.5和设置的IsEnabled为false)和调用基类的ShowDialog的。
public bool? ShowDialog(Action action)
{
bool? result = true;
// start a new thread to start the submitted action
Thread t = new Thread(new ThreadStart(delegate()
{
// start the submitted action
try
{
Dispatcher.UnhandledException += Dispatcher_UnhandledException;
Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
catch (Exception ex)
{
throw ex;
}
finally
{
// close the window
Dispatcher.UnhandledException -= Dispatcher_UnhandledException;
this.DoClose();
}
}));
t.Start();
if (t.ThreadState != ThreadState.Stopped)
{
result = this.ShowDialog();
}
return result;
}
private new bool? ShowDialog()
{
DisableHost();
this.Topmost = true;
return base.ShowDialog();
}
private void DisableHost()
{
if (host != null)
{
host.Dispatcher.Invoke(new Action(delegate()
{
this.Width = host.Width - 20;
host.Cursor = Cursors.Wait;
host.IsEnabled = false;
host.Opacity = 0.5;
}));
}
}
以下是这方面的问题:
这些是我目前想到的主要问题。如何改进这个概念,或者采用其他什么方法来解决这个问题?
提前致谢!
答案 0 :(得分:8)
在开发WPF应用程序时,一点横向思维总是有帮助的。只需Grid
,Rectangle
,bool
属性(您已经拥有)和BooleanToVisibilityConverter
即可轻松满足您的要求,您无需禁用任何控件。
这个想法很简单。在视图内容前添加一个白色Rectangle
,其Opacity
属性设置在0.5
和0.75
之间。数据将其Visibility
属性绑定到视图模型中的bool
属性或后面的代码并插入BooleanToVisibilityConverter
:
<Grid>
<Grid>
<!--Put your main content here-->
</Grid>
<Rectangle Fill="White" Opacity="0.7" Visibility="{Binding IsWaiting,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<!--You could add a 'Please Wait' TextBlock here-->
</Grid>
现在,当您要禁用控件时,只需将bool
属性设置为true
,Rectangle
将使UI显示为淡色:
IsWaiting = true;
答案 1 :(得分:1)