WPF列表框没有重绘

时间:2009-05-26 05:54:50

标签: wpf listbox redraw

我在XAML中定义了一个列表框:

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

SelectedDirectories是类型为List<DirectoryInfo>

的DataContext列表中的属性

作为列表框的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));
            }
        }
    }

2 个答案:

答案 0 :(得分:3)

尝试

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知道要动态添加/删除的内容。

答案 1 :(得分: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的Window,其中包含列表框,文本框和按钮。

更新:保罗贝茨是对的。它的工作原理是因为我每次都从Bound属性返回一个新列表。与列表的数据绑定总是让我感到困惑。 通过更多的修补,简单的方法是:

  • 使FileScanner #Directies返回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);
         }
      }