WPF - 将列表框绑定到列表< string> - 我究竟做错了什么? [英] WPF - bind a listbox to a list<string> - what am I doing wrong?

查看:110
本文介绍了WPF - 将列表框绑定到列表< string> - 我究竟做错了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



到目前为止,我有以下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 =备份配置文件编辑器[新配置文件]Height =480Width =640>
& DockPanel>
< Menu DockPanel.Dock =Top>
< MenuItem Header =File>
< MenuItem Header =打开/>
< / MenuItem>
< / Menu>
< StackPanel Orientation =VerticalDockPanel.Dock =TopMargin =10 10 10 3>
< TextBlock>要备份的项目:< / TextBlock>
< / StackPanel>
& DockPanel DockPanel.Dock =BottomMargin =10 0 10 10>
< StackPanel Orientation =Horizo​​ntal>
< Button Name =AddDirectoryButtonHeight =22.725Width =120Margin =0 0 6 0Click =AddDirectoryButton_Click>添加目录...< / Button>
< Button Name =AddFileButtonHeight =22.725Width =90Margin =0 0 6 0Click =AddFileButton_Click>添加文件...< / Button>
< Button Name =RemoveDirectoriesButtonHeight =22.725Width =75.447Margin =0 0 6 0> Remove< / Button>
< / StackPanel>
< / DockPanel>
< ListBox Name =SelectedItemsMargin =10 0 10 10ItemsSource ={Binding Path = ItemList}/>
< / DockPanel>
< / Window>

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



public $ _ code public public 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);
}
}
}

我比较新对于这样一个简单的问题,WPF和大多数教程似乎过于复杂。我似乎无法在这里任何地方 - 我缺少什么?

解决方案

你应该使用 BindingList< T> ObservableCollection< T> 而不是列表< T>



问题是,要绑定到你想要的方式工作,实施 INotifyCollectionChanged IBindingList 列表< T> 不支持此。






编辑:



在查看您的更改后,仍然有一个问题。



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

  SelectedItems.ItemsSource = null; 

它显式删除了您的绑定,并导致列表框被清除。如果你删除它,你的代码应该按原样工作。



但是,我建议将您的收藏定义和构造函数更改为:

  //每次都不需要空检查,或公共设置器。他们只是引起问题
public ObservableCollection< string> ItemList
{
get;
私人集;
}

//在这里添加构造,现在我们使用的是一个auto-prop
public Main()
{
this.ItemList = new ObservableCollection< string>();
InitializeComponent();
ItemList.Add(test item);
DataContext = this;
}


I'm trying to do something very basic here, something I wouldn't have expected to give me this many problems. I have a public property on my main Window class called ItemList which is of type List<string>. I add to this list throughout the life of the program, and would like the ListBox control I have on my form to automatically update when I add new items to the ItemList property.

So far, I have the following 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>

The relevant code-behind code looks like:

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);
        }
    }
}

I'm relatively new to WPF and most of the tutorials seem overly complicated for such a simple problem. I can't seem to get anywhere here - what am I missing?

解决方案

You should use BindingList<T> or ObservableCollection<T> instead of List<T>.

The problem is that, for binding to work the way you want, it needs to implement INotifyCollectionChanged or IBindingList. List<T> does not support this.


Edit:

After reviewing your changes, there is still one problem.

In the AddFileButton_Click event handler, remove the following line:

SelectedItems.ItemsSource = null;

It is explicitly removing your binding, and causing the list box to clear. If you remove that, your code should work as-is.

However, I do recommend changing your collection definition and constructor to something more like:

    // 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;
    }

这篇关于WPF - 将列表框绑定到列表&lt; string&gt; - 我究竟做错了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆