2009-05-26 42 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); 
        } 
        }