2009-09-26 1 views
1

Я пытался изучить и использовать WPF и привязку данных. У меня есть ListView, который имеет столбец, который будет отображать один из трех изображений, как показано в этом фрагменте:C# WPF OnPropertyChanged В цикле foreach

<GridViewColumn Header="Status" Width="50"> 
    <GridViewColumn.CellTemplate> 
    <DataTemplate> 
     <Image x:Name="TheImage" Height="18"/> 
     <DataTemplate.Triggers> 
      <DataTrigger Binding="{Binding Path=Status}" Value="queued"> 
      <Setter TargetName="TheImage" Property="Source" Value="Images\que_48.png" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=Status}" Value="completed"> 
      <Setter TargetName="TheImage" Property="Source" Value="Images\complete_48.png" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=Status}" Value="failed"> 
      <Setter TargetName="TheImage" Property="Source" Value="Images\fail_48.png" /> 
      </DataTrigger> 
     </DataTemplate.Triggers> 
     </DataTemplate> 
    </GridViewColumn.CellTemplate> 
    </GridViewColumn> 

У меня есть класс (BatchQueueItem), который имеет среди него этот код для обработки PropertyChange Событие:

public string status; 
    public string Status 
    { 
    get { return status; } 
    set 
    { 
     status = value; 
     OnPropertyChanged("Status"); 
    }    
    } 
    // Create the OnPropertyChanged method to raise the event 

    public event PropertyChangedEventHandler PropertyChanged;  
    private void OnPropertyChanged(string status) 
    { 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(status)); 
    } 
    } 

и у меня есть кнопка на странице окна ListView:

private void btnStart_Click(object sender, RoutedEventArgs e) 
{ 
    foreach (var item in listView1.Items) 
    { 
    BatchQueueItem bqi = (BatchQueueItem)item; 
    string currFile = bqi.CurrFile; 
    if (mainWindow.isIsbnInFileName(ref currFile)) 
    { 
     bqi.Status = "completed"; 
    } 
    else 
    { 
     bqi.Status = "failed"; 
    } 
    } 
} 

проблема, которую я имею, что изображения не не обновляются, пока цикл Еогеасп завершен и кнопок BTN tart_Click() завершен. Как только это произойдет, все изображения будут обновляться, как и ожидалось, просто сразу же не итеративно.

То, что я хочу, и то, что я думал, будет состоять в том, что каждая итерация цикла foreach обновит изображение соответствующей строки. Несомненно, мне не хватает чего-то важного в том, как все это работает. Какие-нибудь советы?

ответ

4

Проблема, с которой я столкнулась, заключается в том, что изображения не обновляются до тех пор, пока цикл foreach не завершится и не завершится метод btnStart_Click(). Как только это произойдет, все изображения будут обновляться, как и ожидалось, просто сразу же не итеративно.

То, что я хочу, и то, что я думал, будет состоять в том, что каждая итерация цикла foreach обновит изображение соответствующей строки. Несомненно, мне не хватает чего-то важного в том, как все это работает. Какие-нибудь советы?

Это вопрос того, как вы обновляете.

Проблема не в том, что пользовательский интерфейс не обновляется - внутренне он это делает. Проблема в том, что вы делаете это обновление и свой цикл foreach в основном потоке пользовательского интерфейса. Когда вы это сделаете, пользовательский интерфейс будет полностью заблокирован (а не обновляется/перерисовываться) до тех пор, пока ваша операция не будет завершена на 100%, и насос сообщений может снова запуститься.

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

Когда у вас есть длинные операции бегов, это имеет несколько преимуществ:

  1. Вы можете получить обратную связь экземпляра/статус в вашем пользовательском интерфейсе
  2. Вашего пользовательского интерфейс остается отзывчивым пока ваша операция выполняется.
+3

На самом деле вам не нужно использовать Dispatcher.Invoke здесь: WPF автоматически упорядочивает уведомление PropertyChanged по потокам для привязок, поэтому вы можете обновить свойство непосредственно из рабочего потока. –

+0

Хорошо, вы, ребята, потеряли меня здесь. Любой шанс на ссылку или фрагмент кода, чтобы прояснить ситуацию немного мольбы? – Dave

0

Почему это проблема?

Похоже, что этот цикл должен занять микросекунды. Если это так, то нет заметной разницы в том, будут ли элементы управления перерисовывать в конце цикла или нет.

Если список такой большой, вы должны рассмотреть его подкачку в любом случае.

Если требуется, чтобы получить данные, вы должны делать это в другом потоке, как было предложено выше.Однако, если это так сложно, я бы сказал, что вы действительно должны смотреть на отсутствие сложной логики в обработчике событий нажатия кнопки и переходить к большей части модели MVVM.

+0

Хорошо, я изучу использование другой темы. Это не очень сложная логика, но некоторые итерации могут занимать 10-15 секунд, поскольку она анализирует текстовый файл, и список обычно будет составлять 20-30 элементов. – Dave

0

Спасибо за помощь! Я смог заставить это работать так, как я хотел, как только вы заставили меня указывать в правильном направлении. С вашими намеками и этой ссылкой: Worker Threads & Dispatcher Мне удалось получить это с несколькими дополнительными строками кода. Плюс я еще раз узнал что-то новое о WPF.