我在渲染时需要一个Progressbar / Busyindicator,因为在GUI上有很多TextBoxes和不同的Controls。由于具有CellTemplate Selector的动态Columns,无法虚拟化DataGrid。
所以我真的需要一个Progressbar / Busyindicator,以便应用程序似乎不会被冻结。 我的方法是在STA-Thread中设置一个新窗口,当我知道GUI将呈现并在之后关闭它。 问题是,我无法设置Window-Owner。因此,如果应用程序未被冻结(无渲染,只是一个任务),则用户可以将窗口置于前景之后。设置Window Topmost似乎不是一个很好的解决方案。
在应用程序渲染时获取Progressbar / Busyindicator的任何其他想法?
我的解决方案代码:
线程启动/停止Busywindow:
private void ShowBusyWindow(bool show)
{
if (show)
{
if (BusyThread == null || !BusyThread.IsAlive)
{
BusyThread = new Thread(new ThreadStart(() =>
{
// Create our context, and install it:
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
BusyWindow window = new BusyWindow();
// When the window closes, shut down the dispatcher
window.Closed += (s, e) =>
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
window.ShowInTaskbar = true;
window.Show();
// Start the Dispatcher Processing
System.Windows.Threading.Dispatcher.Run();
}));
BusyThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
BusyThread.IsBackground = true;
BusyThread.Start();
}
}
else
{
if (BusyThread != null && BusyThread.IsAlive)
BusyThread.Abort();
}
}
Busywindow:
<Window x:Class="MEval.Wpf.View.BusyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="BusyWindow" SizeToContent="WidthAndHeight"
WindowStyle="None"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
>
<Grid>
<xctk:BusyIndicator IsBusy="True">
</xctk:BusyIndicator>
</Grid>
在渲染操作之前和之后调用线程:
private DataTable _SelectedMeasurementData;
public DataTable SelectedMeasurementData
{
get { return _SelectedMeasurementData; }
set {
if (value != null)
{
Messenger.Default.Send<BusyWindowMessage>(new BusyWindowMessage(true));
}
_SelectedMeasurementData = value;
RaisePropertyChanged("SelectedMeasurementData");
this.dispatcherProvider.CurrentDispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, new Action(() =>
{
Messenger.Default.Send<BusyWindowMessage>(new BusyWindowMessage(false));
}));
}
}