WPF - 将列表框绑定到列表<string> - 我做错了什么?

Chr*_*ris 2 .net data-binding wpf listbox

我想在这里做一些非常基本的事情,我不希望给我这么多问题.我在我的主要类Window上有一个名为ItemList的公共属性List<string>.我在程序的整个生命周期中添加了这个列表,并希望我在表单上的ListBox控件在我向ItemList属性添加新项时自动更新.

到目前为止,我有以下XAML:

<Window x:Class="ElserBackupGUI.Main"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Backup Profile Editor [New Profile]" Height="480" Width="640">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="File">
                <MenuItem Header="Open"/>
            </MenuItem>
        </Menu>
        <StackPanel Orientation="Vertical" DockPanel.Dock="Top" Margin="10 10 10 3">
            <TextBlock>Items to backup:</TextBlock>
        </StackPanel>
        <DockPanel DockPanel.Dock="Bottom" Margin="10 0 10 10">
            <StackPanel Orientation="Horizontal">
                <Button Name="AddDirectoryButton" Height="22.725" Width="120" Margin="0 0 6 0" Click="AddDirectoryButton_Click">Add Directory...</Button>
                <Button Name="AddFileButton" Height="22.725" Width="90" Margin="0 0 6 0" Click="AddFileButton_Click">Add File...</Button>
                <Button Name="RemoveDirectoriesButton" Height="22.725" Width="75.447" Margin="0 0 6 0">Remove</Button>
            </StackPanel>
        </DockPanel>
        <ListBox Name="SelectedItems" Margin="10 0 10 10" ItemsSource="{Binding Path=ItemList}"/>
    </DockPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

相关的代码隐藏代码如下所示:

public partial class Main : Window
{
    private string _lastFolder = string.Empty;
    private ObservableCollection<string> _itemList = new ObservableCollection<string>();

    public ObservableCollection<string> ItemList {
        get { return _itemList ?? (_itemList = new ObservableCollection<string>()); }
        set { _itemList = value; }
    }

    public Main()
    {
        InitializeComponent();
        ItemList.Add("test item");
        DataContext = this;
    }

    private void AddDirectoryButton_Click(object sender, RoutedEventArgs e)
    {
        FolderBrowserDialog dialog = new FolderBrowserDialog();
        if (!string.IsNullOrEmpty(_lastFolder))
            dialog.SelectedPath = _lastFolder;

        if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            _lastFolder = dialog.SelectedPath;
            ItemList.Add(dialog.SelectedPath);
        }
    }

    private void AddFileButton_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog dialog = new OpenFileDialog();
        if (!string.IsNullOrEmpty(_lastFolder))
            dialog.InitialDirectory = _lastFolder;

        if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            _lastFolder = System.IO.Path.GetDirectoryName(dialog.FileName);
            SelectedItems.ItemsSource = null;
            ItemList.Add(dialog.FileName);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我对WPF比较陌生,大多数教程对于这么简单的问题似乎过于复杂.我似乎无法到达这里 - 我错过了什么?

Ree*_*sey 8

你应该使用BindingList<T>ObservableCollection<T>代替List<T>.

问题是,为了以你想要的方式绑定工作,它需要实现INotifyCollectionChangedIBindingList. List<T>不支持这个.


编辑:

在查看您的更改后,仍然存在一个问题.

在AddFileButton_Click事件处理程序中,删除以下行:

SelectedItems.ItemsSource = null;
Run Code Online (Sandbox Code Playgroud)

它明确地删除了您的绑定,并导致列表框清除.如果删除它,您的代码应该按原样运行.

但是,我建议将集合定义和构造函数更改为更像:

    // No need for the null checking every time, or public setter.  They just cause issues
    public ObservableCollection<string> ItemList
    {
        get;
        private set;
    }

    // Add construction here, now that we're using an auto-prop
    public Main()
    {
        this.ItemList = new ObservableCollection<string>();
        InitializeComponent();
        ItemList.Add("test item");
        DataContext = this;
    }
Run Code Online (Sandbox Code Playgroud)