Как заблокировать пользовательский интерфейс во время асинхронных операций в WPF - PullRequest
4 голосов
/ 17 марта 2010

У нас есть приложение WPF (фактически приложение VSTO WPF). В некоторых элементах управления есть несколько элементов, которые при нажатии загружают данные из веб-службы и обновляют пользовательский интерфейс. Прямо сейчас мы выполняем эти веб-запросы синхронно, блокируя поток пользовательского интерфейса, пока ответ не вернется. Это предотвращает щелчок пользователя по приложению во время загрузки данных, потенциально переводя его в недопустимое состояние для обработки данных при их возврате.

Конечно, приложение перестает отвечать на запросы, если запрос занимает много времени. В идеале мы хотели бы, чтобы кнопка отмены была активной в это время, но не более того. Есть ли умный способ сделать это, или мы должны будем переключать запросы для асинхронного выполнения с использованием backgroundworker и писать что-то, что отключает все элементы управления, кроме кнопки отмены, пока выполняется запрос?

edit: для действий, которые мы уже ожидаем, чтобы они выполнялись долго (загрузка файла и т. Д.), Мы открываем диалоговое окно прогресса. Например, вы ожидаете, что действие будет довольно быстрым (максимум пару секунд), но иногда занимает больше времени. В этих обстоятельствах вспыхивание целого окна на мгновение слишком отвлекает.

Ответы [ 5 ]

4 голосов
/ 17 марта 2010

Ваши интерактивные элементы управления должны быть связаны с командами, и команды должны иметь CanBeExecuted, возвращающие false, когда выполняется фоновая задача. Если вы сделаете это, элементы управления, связанные с этими командами, автоматически отключатся и включатся.

Вы можете избежать дублирования большого количества кода, создав класс команд, который реализует проверку фоновой задачи в процессе, а затем извлекая все ваши команды (кроме, конечно, команды отмены) из этого класса.

1 голос
/ 17 марта 2010

Silverlight Toolkit имеет элемент управления BusyIndicator. Инструментарий с открытым исходным кодом, поэтому вы легко сможете перенести его в WPF.

Он отключает и выделяет все, что ему назначено, при установке для его свойства IsBusy значения true в коде или путем привязки его к модели. Использование выглядит следующим образом:

<ctl:BusyIndicator>
    <StackPanel x:Name="myDataArea">
        <Button Content="Load Data" />
        <DataGrid x:Name="myDataGrid" />
    </StackPanel>
</ctl:BusyIndicator>
1 голос
/ 17 марта 2010

Один из способов - поместить полупрозрачный холст поверх тех частей пользовательского интерфейса, которые недоступны во время ожидания ответа, и в центре поместить сообщение с кнопкой отмены.

1 голос
/ 17 марта 2010

Когда вы делаете свой асинхронный запрос в отдельном потоке, покажите модальное диалоговое окно с кнопкой «Отмена» (и, возможно, индикатор выполнения или другой индикатор активности).

Таким образом, пользователь не может взаимодействовать с базовым пользовательским интерфейсом, и он все еще получает сообщение о том, что что-то происходит ... и возможность отменить его.

0 голосов
/ 17 марта 2010

Я не могу придумать простой способ, кроме отключения всех элементов управления, кроме «Отмена».

Сказав это, пользователь может почувствовать себя лучше, если вы отобразите «рабочий» или диалог прогресса с помощью только кнопки отмены.

Вы можете использовать этот журнал для отображения полезной информации о ходе выполнения веб-запросов и любых сообщений об ошибках, которые могут вернуться.

...