WPF Binding Render Gui Progress - PullRequest
       22

WPF Binding Render Gui Progress

3 голосов
/ 29 декабря 2010

Я знаю, что здесь и там есть несколько реализаций, но я все еще не смог «заблокировать» что-то действительно полезное ...

Всякий раз, когда я устанавливаю какой-либо компонент DataContext или ItemsSource на какой-то большой объект, существует такой «графический интерфейс с задержкой на визуализацию», который делает приложение действительно раздражающим (даже при использовании виртуализации).

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

Есть ли достойный способ достичь следующих?

Большое спасибо

Ответы [ 3 ]

3 голосов
/ 09 января 2011

Пример Zamboni очень хороший, но все еще не решает проблему замороженного графического интерфейса пользователя .

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

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

CompositionTarget.Rendering += ReportRenderProgress;

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

2 голосов
/ 03 января 2011

BackgroundWorker имеет все необходимое.

EDIT

В WPF диспетчер используется автоматически для вызова многопоточных вызовов методов. Проверьте Создание более отзывчивых приложений с помощью Dispatcher в журнале MSDN.

Я также собрал некоторые фрагменты кода из ViewModel, который показывает BackgroundWorker, обновляющий индикатор выполнения.

<ProgressBar 
    VerticalContentAlignment="Stretch" VerticalAlignment="Stretch"
    HorizontalAlignment="Stretch"
    Minimum="0" Maximum="100"
    Value="{Binding Path=BarPosition, Mode=TwoWay}"/>


// configure the background worker...
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.WorkerReportsProgress = true;
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(_backgroundWorker_ProgressChanged);

// control progress bar position
private int _barPosition = 0;
public int BarPosition
{
   get { return _barPosition; }
   set
   {
      _barPosition = value;
      OnPropertyChanged("BarPosition");
   }
}

// long operation
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
  BackgroundWorker bw = sender as BackgroundWorker;
  if (bw != null)
  {
     int pos;

     for (int i = 0; i < 100; ++i
     {
        // report progress here for our long running operation..
        pos = i/100;
        bw.ReportProgress(pos);
        Thread.Sleep(1000);            // fake long operation
     }
  }
}

// report progress,,,
void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
   BackgroundWorker bw = sender as BackgroundWorker;
   if (bw != null)
   {
      BarPosition = e.ProgressPercentage;
   }
}

// reset scroll bar position
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   BackgroundWorker bw = sender as BackgroundWorker;
   if (bw != null)
   {
     BarPosition = 0;

     // Forcing the CommandManager to raise the RequerySuggested event to refresh UI...
     CommandManager.InvalidateRequerySuggested();
   }
}
2 голосов
/ 29 декабря 2010

Это на самом деле проблема. Вы используете поток GUI для заполнения данных (из структуры объекта в GUI). Поток графического интерфейса необходим как для чтения очереди сообщений Windows (предотвращение зависания приложения, так и для перемещения приложения / ответа), а также для любых обновлений графического интерфейса.

Одним из решений может быть медленное заполнение структуры объекта после привязки. Это должно быть сделано из потока GUI, чтобы вы могли добавить DoEvents () и / или какой-нибудь индикатор процента + принудительное обновление, чтобы приложение казалось живым.

Мне интересно узнать, есть ли у кого-нибудь лучшее решение.

...