WPF Listbox не перерисовывается - PullRequest
0 голосов
/ 26 мая 2009

У меня есть список, определенный в XAML как:

<ListBox x:Name="directoryList"
                 MinHeight="100" 
                 Grid.Row="0"
                 ItemsSource="{Binding Path=SelectedDirectories}"/>

SelectedDirectories - это свойство в списках DataContext типа List<DirectoryInfo>

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

Есть идеи, почему?

РЕДАКТИРОВАТЬ: INotifyPropertyChanged реализация

public class FileScannerPresenter : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private FileScanner _FileScanner;

        public FileScannerPresenter()
        {
            this._FileScanner = new FileScanner();
        }

        public List<DirectoryInfo> SelectedDirectories
        {
            get
            {
                return _FileScanner.Directories;
            }
        }

        public void AddDirectory(string path)
        {
            this._FileScanner.AddDirectory(path);
            OnPropertyChanged("SelectedDirectories");
        }

        public void OnPropertyChanged(string property)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }

Ответы [ 2 ]

3 голосов
/ 26 мая 2009

Попробуйте

ObservableCollection<DirectoryInfo> 

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

class SomeWindow : Window {
    public ObservableCollection<DirectoryInfo> SelectedDirectories {get; private set;}

    SomeWindow() { SelectedDirectories = new ObservableCollection<DirectoryInfo>(); }

    public void AddDirectory(string path) {
        SelectedDirectories.Add(new DirectoryInfo(path));
    }
}

Если вы в конечном итоге используете этот класс FileScanner, вам нужно вместо этого реализовать INotifyCollectionChanged - таким образом, ListBox знает, что добавлять / удалять динамически.

0 голосов
/ 26 мая 2009

(см. Обновление ниже) . WPF вроде работает нормально. Я поместил ваш код в новый проект. Список обновляется всякий раз, когда я нажимаю кнопку, чтобы вызвать AddDirectory. Вам не нужно больше менять код. Кажется, проблема в чем-то другом .. Есть ли несколько потоков в вашем интерфейсе?

У меня не было типа FileScanner. Поэтому я создал пустышку следующим образом.

public class FileScanner
   {
      string _path;
      public FileScanner()
      {     _path = @"c:\";      }
      public List<DirectoryInfo> Directories
      {
         get
         {
            return Directory.GetDirectories(_path).Select(path => new DirectoryInfo(path)).ToList();
         }
      }

      internal void AddDirectory(string path)
      {         _path = path;      }
   }

Нет изменений в вашем классе FileScannerPresenter. Или ваш список XAML. Я создал окно с DockPanel, содержащее ваш список, текстовое поле и кнопку.

Обновление: Пол Беттс прав. Это работает, потому что я каждый раз возвращаю новый список из свойства Bound. Связывание данных со списками всегда портит меня. С большим количеством возни, легкий способ сделать это:

  • Make FileScanner # Каталоги возвращают ObservableCollection<DirectoryInfo> (который реализует INotifyCollectionChanged для вас). Измените все подписи полностью, чтобы вернуть этот тип вместо List<DirectoryInfo>
  • FileScanner и FileScannerPresenter сами по себе не должны реализовывать интерфейс INotifyXXX.

    //  in FileScanner class def         
      public ObservableCollection<DirectoryInfo> Directories
      {
         get
         {  return _DirList;  }
      }
      internal void AddDirectory(string path)
      {
         _path = path;
         //var newItems = Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList();
         //_DirList.Concat( newItems );  -- doesn't work for some reason.
         foreach (var info in Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList())
         {
            _DirList.Add(info);
         }
      }
    
...