C# 将列表框绑定到ObservableCollection仅适用于第一项

C# 将列表框绑定到ObservableCollection仅适用于第一项,c#,data-binding,listbox,observablecollection,inotifypropertychanged,C#,Data Binding,Listbox,Observablecollection,Inotifypropertychanged,我正在尝试制作一个应用程序,将自定义对象(位置)的列表/集合等与列表框绑定,以便: 列表框显示每个对象的选定属性(“名称”) 在列表框中选择一项将更改列表框中的“当前”项 列表/集合 在列表框中添加/删除项目,在列表框中添加/删除项目 列表/集合 添加/删除列表/集合中的项目,则添加/删除列表/集合中的项目 列表框 更改项目的“显示”属性时,会在中更改项目 列表框 到目前为止,我的代码是: namespace DataBindingTest { public partial class

我正在尝试制作一个应用程序,将自定义对象(位置)的列表/集合等与列表框绑定,以便:

  • 列表框显示每个对象的选定属性(“名称”)
  • 在列表框中选择一项将更改列表框中的“当前”项 列表/集合
  • 在列表框中添加/删除项目,在列表框中添加/删除项目 列表/集合
  • 添加/删除列表/集合中的项目,则添加/删除列表/集合中的项目 列表框
  • 更改项目的“显示”属性时,会在中更改项目 列表框
到目前为止,我的代码是:

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

我只是将类放置在类Form1之外,因为我需要在整个名称过程中使用它,但我认为它不会改变什么。

不确定原因,但它似乎只更新所选项目。这并不优雅,但似乎是一个权宜之计:

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;
}
这似乎是ObservableCollection的一个问题(可能是bug?)!如果改用BindingList,效果很好!!在这里找到的。经过3天的搜索

编辑

命名空间数据绑定测试
{
公共部分类Form1:Form
{
绑定源bs;
BindingList位置=新建BindingList();
地点1=新地点(“pl1”,2.2);
地点2=新地点(“pl2”,2.3);
公共表格1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
bs=新的BindingSource();
地点。增加(地点1);
地点。增加(地点2);
bs.DataSource=地点;
listBox1.DataSource=bs;
listBox1.DisplayMember=“Name”;
添加(新绑定(“Text”,bs,“Name”,true,DataSourceUpdateMode.OnPropertyChanged));
地点3=新地点(“pl3”,0);
bs.添加(第3处);
地点[2]。名称=“地点3”;
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
地点[0]。名称=“地点1”;
地点[1]。名称=“地点2”;
}
}
公共类位置:InotifyProperty已更改
{
公共事件属性更改事件处理程序属性更改;
字符串名;
双重损失;
公共场所(字符串n,双l)
{
name=n;
损失=l;
}
公共字符串名
{
获取{返回名称;}
设置
{
名称=值;
不动产变更(“名称”);
}
}
公众双重损失
{
获取{返回损失;}
设置{loss=value;}
}
受保护的无效OnPropertyChanged(字符串PropertyName)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
处理程序(这是新的PropertyChangedEventArgs(PropertyName));
}
}
}

感谢您的回复。问题是,我希望在属性更改时自动更新列表框。我添加该按钮的原因是为了检查是否发生了这种情况。您说过它只更新listbox的selectedItem,为此,我将尝试自动化该过程。ObservableCollection似乎在通知其项的更改时遇到问题。BindingList做的很好!当然,我怎么能忘记BindingList呢。很高兴看到你把它整理好了。你能把工作代码作为答案贴出来吗?我刚试过你的代码,注意到只有选中的项目会被更新(如果你在listbox中选择第二行,那么处理程序在[0]处将为空。)@har07让我知道这是否对你有效,将ObservableCollection更改为BindingList也对我有效。所以,只需将其作为答案发布,并将其标记为已接受。我一直在使用ObservaleCollection,它在WPF和Windows Phone(任何使用XAML绑定的东西)中的工作都非常出色,但似乎不适合Windows窗体数据绑定—它们在不同的情况下使用。WPF支持INotifyCollectionChanged(这是ObservableCollection库),但DataGridView仅支持IBindingList更改。INotifyCollectionChanged对更改更有效。ObservableCollection可以支持这两个接口。但事实并非如此。
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;
}
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));
        }
    }

}