题
我在 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); } }