2009-05-26 39 views
0

我在XAML定義爲列表框:WPF列表框不重繪

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

的SelectedDirectories上類型的列表的DataContext List<DirectoryInfo>

的類,這是一個屬性爲列表框的datacontext實現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)); 
      } 
     } 
    } 

回答

3

嘗試

ObservableCollection<DirectoryInfo> 

而是 - 你觸發了整個列表框的刷新無緣無故的,你不需要讓你的主機類實現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代替 - 這樣,列表框知道添加/刪除動態。

+0

你說得對w.r.t.爲什麼我以前的代碼段工作。更新。 +1 – Gishu 2009-05-27 05:58:30

+0

我最終做的是將集合抽象到ObservableCollection中的一個演示者類中,然後只在需要時將其傳遞給scanner類。 – benPearce 2009-06-05 06:06:53

0

(見下更新)。 WPF似乎工作正常。我把你的代碼放到一個新的項目中。 每當我按一下按鈕列表框更新調用AddDirectory。你不應該需要更多的代碼更改。 這個問題似乎是別的東西..在你的UI有多個線程?

我沒有了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屬性返回一個新列表。與列表的數據綁定總是給我打擾。 隨着越來越多的修修補補,簡單的方法來做到這一點是:

  • 製作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); 
        } 
        }