我正在尝试制作一个应用程序,将自定义对象(Places)的List/Collection等与列表框绑定,以便:
- ListBox显示每个对象的选定属性("名称")
- 在ListBox中选择一个项目会更改中的"当前"项目列表/集合
- 在ListBox中添加/删除项,在中添加/移除项列表/集合
- 在列表/集合中添加/删除项目,在中添加/移除项目列表框
- 更改项目的显示属性,更改中的项目列表框
到目前为止,我的代码是:
namespace DataBindingTest
{
public partial class Form1 : Form
{
BindingSource bs;
ObservableCollection<Place> places = new ObservableCollection<Place>();
Place place1 = new Place("pl1", 2.2);
Place place2 = new Place("pl2", 2.3);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bs = new BindingSource();
places.Add(place1);
places.Add(place2);
bs.DataSource = places;
listBox1.DataSource = bs;
listBox1.DisplayMember = "Name";
listBox1.DataBindings.Add(new Binding("Text", bs, "Name", true, DataSourceUpdateMode.OnPropertyChanged));
}
public class Place : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string name;
double losses;
public Place(string n, double l)
{
name = n;
losses = l;
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
public double Losses
{
get { return losses; }
set { losses = value; }
}
protected void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
private void button1_Click(object sender, EventArgs e)
{
places[0].Name = "Place 1";
places[1].Name = "Place 2";
}
}
当为places[0]
调用OnPropertyChanged
时,这是可以的,当为places[1]
调用时,处理程序为null!为什么会发生这种情况?
解决方案
ObservableCollection似乎有问题(可能是bug?)!如果我改为使用BindingList,它可以正常工作!!在这里找到的。经过3天的搜索。
编辑
namespace DataBindingTest
{
public partial class Form1 : Form
{
BindingSource bs;
BindingList<Place> places = new BindingList<Place>();
Place place1 = new Place("pl1", 2.2);
Place place2 = new Place("pl2", 2.3);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bs = new BindingSource();
places.Add(place1);
places.Add(place2);
bs.DataSource = places;
listBox1.DataSource = bs;
listBox1.DisplayMember = "Name";
listBox1.DataBindings.Add(new Binding("Text", bs, "Name", true, DataSourceUpdateMode.OnPropertyChanged));
Place place3 = new Place("pl3", 0);
bs.Add(place3);
places[2].Name = "Place3";
}
private void button1_Click(object sender, EventArgs e)
{
places[0].Name = "Place 1";
places[1].Name = "Place 2";
}
}
public class Place : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string name;
double losses;
public Place(string n, double l)
{
name = n;
losses = l;
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
public double Losses
{
get { return losses; }
set { losses = value; }
}
protected void OnPropertyChanged(string PropertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
我只是把Class Place放在Class Form1之外,因为我需要在整个命名空间中使用它,但我认为它不会改变什么。
ObservableCollection似乎有问题(可能是bug?)!如果我改为使用BindingList,它可以正常工作!!在这里找到的。经过3天的搜索。
编辑
namespace DataBindingTest
{
public partial class Form1 : Form
{
BindingSource bs;
BindingList<Place> places = new BindingList<Place>();
Place place1 = new Place("pl1", 2.2);
Place place2 = new Place("pl2", 2.3);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bs = new BindingSource();
places.Add(place1);
places.Add(place2);
bs.DataSource = places;
listBox1.DataSource = bs;
listBox1.DisplayMember = "Name";
listBox1.DataBindings.Add(new Binding("Text", bs, "Name", true, DataSourceUpdateMode.OnPropertyChanged));
Place place3 = new Place("pl3", 0);
bs.Add(place3);
places[2].Name = "Place3";
}
private void button1_Click(object sender, EventArgs e)
{
places[0].Name = "Place 1";
places[1].Name = "Place 2";
}
}
public class Place : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string name;
double losses;
public Place(string n, double l)
{
name = n;
losses = l;
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
public double Losses
{
get { return losses; }
set { losses = value; }
}
protected void OnPropertyChanged(string PropertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
不确定原因,但它似乎只是更新所选项目。这并不优雅,但它似乎是一个权宜之计:
private void button1_Click(object sender, EventArgs e)
{
int actualIndex = listBox1.SelectedIndex;
listBox1.SelectedIndex = 0;
places[0].Name = "Place 1";
listBox1.SelectedIndex = 1;
places[1].Name = "Place 2";
listBox1.SelectedIndex = actualIndex;
}