Попытка отобразить сообщение "Пожалуйста, подождите" в WPF во время длительной операции
У меня есть please wait
TextBlock
в моем XAML, чей Visibility
собственность связана с IsBusy
Свойство на моей ViewModel (которая реализует INotifyPropertyChanged
). Отдельная кнопка запускает длительный (2-3 секунды) процесс, например:
IsBusy = true;
try
{
// Do some long-running process
}
finally
{
IsBusy = false;
}
Но please wait
сообщение никогда не появляется Я предполагаю, что операция выполняется в потоке пользовательского интерфейса и, следовательно, не дает ей возможность обновить? Это работает, если я запускаю приведенный выше код в отдельном потоке, но я не хочу, чтобы пользователь что-либо делал во время выполнения операции - я рад, что пользовательский интерфейс freeze
,
Как я могу отобразить please wait
сообщение? Или мне лучше запустить его в фоновом потоке и (как-то) заблокировать пользовательский интерфейс на время? Я использую.Net 4 кстати.
3 ответа
Вы правы, это не обновление, потому что вы запускаете код в том же потоке, поэтому рендеринг не будет продолжаться до тех пор, пока ваш процесс не завершится.
Вы сказали, что не используете фоновый поток, потому что не хотите, чтобы пользователь что-либо делал во время выполнения операции, но никогда не стоит полностью блокировать ваше приложение, как это.
Лучшим решением было бы связать IsEnabled
вашей формы / окна /UserControl/ и т. д. в IsBusy
имущество. Затем, когда она становится занятой, вся форма отключается, чтобы пользователь не мог ее изменить, не блокируя приложение.
Вначале Visibility
собственность не bool
так что если вы хотите связать bool
переменная к нему вам нужно использовать IValueConverter
и, во-вторых, да, вы правы, в то время как поток пользовательского интерфейса занят вашей продолжительной операцией, он не будет выполнять ничего другого, включая изменение видимости.
Я бы предложил использовать WPF Toolkit
BusyIndicator
ожидайте поставить свою собственную панель, у нее есть IsBusy bool
имущество.
Кроме того, Froozen UI не является удобным для пользователя, как правило, я использую этот фрагмент
IsBusy = true;
Task.Factory.StartNew(() =>
{
// Do work.
})
.ContinueWith(t=>IsBusy=false,
TaskScheduler.FromCurrentSynchronizationContext());
Также обратите внимание, чтобы проверить ошибки в ContinueWith
метод, или вы получите исключение на Task
располагать
Если вы выполняете свой код в отдельном потоке, вы все равно можете получить доступ к интерфейсу через метод Dispatcher.BeginInvoke.
if (!YOURCONTROL.Dispatcher.CheckAccess())
{
YOURCONTROL.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate()
{
//do something with the control/form/...
}));
}
else
{
//update your control
}