我在 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));
            }
        }
    }
有帮助吗?

解决方案

尝试

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代替 - 这样,列表框知道添加/删除动态

其他提示

(请参阅下面的更新). 。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#Directories 返回 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);
         }
      }
    
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top