首页 > 解决方案 > WPF 列表框未填充来自 ObservableCollection 的项目

问题描述

主窗口正在监听插入/拔出 USB 设备。如果它是 USB 密钥/磁盘,它会从该设备收集文件列表并在第二个窗口中显示该列表。

在调试时,我可以看到 NewUsbFiles observablecollection 填充了 117 个项目。我看到 UsbFile 属性(在调用 showdialog 之前)有 117 个项目,但列表框仍然是空的。

有什么想法吗 ?

填充/创建第二个窗口的方法:

NewUsbFiles = new ObservableCollection<UsbFile>();
UpdateNewUsbFiles(driveName);

Application.Current.Dispatcher.Invoke(delegate
{
   var usbFileSelector = new UsbFileSelector()
   {
       Owner = this,
       UsbFiles = NewUsbFiles
    };
    usbFileSelector.ShowDialog();
});

UsbFile 类:

 public class UsbFile 
    {
        public string UsbFileName { get; set; }
        public string OnTableFileName { get; set; }
        public bool Ignored { get; set; } = false;

        public UsbFile(string fileName)
        {
            var fileInfo = new FileInfo(fileName);
            UsbFileName = fileInfo.FullName;
            OnTableFileName = $"{fileInfo.CreationTime:yyMMddHHmmsss}_{fileInfo.Name}";
        }
    }

第二个窗口的 XAML:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:MainWindow="clr-namespace:PartyPictures.WPF.MainWindow" x:Name="wUsbFileSelector"
    x:Class="PartyPictures.WPF.UsbFileSelector"
        mc:Ignorable="d"
        Title="USB" HorizontalAlignment="Center" VerticalAlignment="Center" WindowStyle="ToolWindow" ScrollViewer.VerticalScrollBarVisibility="Auto" SizeToContent="WidthAndHeight">
    <StackPanel x:Name="spUsbFileList">
        <ListBox  x:Name="ImageListbox"
                  DataContext="{Binding ElementName=wUsbFileSelector}"
                 ItemsSource="{Binding UsbFiles}" 
                 Background="AliceBlue" ScrollViewer.HorizontalScrollBarVisibility="Disabled" MinWidth="200" MinHeight="200">
        </ListBox>
    </StackPanel>
</Window>

第二个窗口的代码隐藏:

public partial class UsbFileSelector : Window
    {
        public ObservableCollection<UsbFile> UsbFiles { get; set; } = new ObservableCollection<UsbFile>();

        public UsbFileSelector()
        {
            InitializeComponent();
        }
    }

标签: c#wpflistboxobservablecollection

解决方案


在窗口内,您可以看到 InitializeComponent 方法。它创建在 XAML 中定义的所有内容并应用所有绑定。在使用您的空集合(您使用默认属性值创建)应用绑定后,绑定将不知道该属性的任何更改,这是正确的答案。

但是实现 INotifyPropertyChanged 更多的是关于视图模型实例,而不是视觉。

如果你想绑定,我真的建议你对窗口和控件使用依赖属性。有一些原因:

  1. 依赖属性设置器具有内置的通知机制。
  2. 如果将一个 DP 绑定到另一个 DP,则值在它们之间共享。
  3. 毕竟是WPF方法=)

这是更改后窗口的外观

    public partial class UsbFileSelector : Window
    {
        public static readonly DependencyProperty UsbFilesProperty = 
            DependencyProperty.Register("UsbFiles", typeof(ObservableCollection<UsbFile>), typeof(UsbFileSelector));

        public ObservableCollection<UsbFile> UsbFiles 
        {
            get { return (ObservableCollection<UsbFile>) GetValue(UsbFilesProperty); }
            set { SetValue(UsbFilesProperty, value); }
        }

        public UsbFileSelector()
        {
            InitializeComponent();
        }
    }

此外,我强烈建议您在为 WPF 开发时使用一些 WPF 检查器工具,例如 snoop。您可以在应用程序运行时浏览控件和属性,并可以从代码或 stackoverflow 中快速找到问题 =)


推荐阅读