WPF - 将列表框绑定到列表< string> - 我究竟做错了什么? [英] WPF - bind a listbox to a list<string> - what am I doing wrong?
问题描述
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 =Horizontal>
< 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 - 将列表框绑定到列表< string> - 我究竟做错了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!