Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在WinForms中使用IBindingList进行数据绑定在空列表上失败_C#_Winforms_Data Binding - Fatal编程技术网

C# 在WinForms中使用IBindingList进行数据绑定在空列表上失败

C# 在WinForms中使用IBindingList进行数据绑定在空列表上失败,c#,winforms,data-binding,C#,Winforms,Data Binding,我在实现自己的集合时遇到了一个特殊问题,该集合应该支持IBindingList 我有一个特定数据类(DataCollection)的集合类(DataItem)。集合实现接口IBindingList,IList,IList,DataItem实现INotifyPropertyChanged(并具有用于数据绑定的公共属性) 当我试图通过设置网格的DataSource属性将集合绑定到DataGridView时,如果在绑定时集合不是空的,则它可以正常工作。否则,如果集合为空,则网格会在从集合中添加或删除行

我在实现自己的集合时遇到了一个特殊问题,该集合应该支持
IBindingList

我有一个特定数据类(
DataCollection
)的集合类(
DataItem
)。集合实现接口
IBindingList
IList
IList
DataItem
实现
INotifyPropertyChanged
(并具有用于数据绑定的公共属性)

当我试图通过设置网格的
DataSource
属性将集合绑定到
DataGridView
时,如果在绑定时集合不是空的,则它可以正常工作。否则,如果集合为空,则网格会在从集合中添加或删除行(即
数据项
)时发出通知,但单元格保持为空。与此问题相关的是,在
AutoGenerateColumns=true
的情况下,网格无法识别数据类的公共成员,并且无法生成列

我还尝试了使用
绑定列表
绑定我的
数据项
。在这种情况下,即使在设置
DataSource
时列表为空,网格也能正常工作。另一方面,如果我使用
绑定列表
(但与内容相同的
数据项
),则行为与我的
数据收集
一样错误。我想问题是,如果在绑定列表时列表为空,那么数据绑定无法正确检测
DataItem
类型,并且在稍后将项目添加到集合时也无法恢复

重要的是,如果集合在绑定时不是空的,它就可以工作

请注意,指定列时也会发生相同的错误:

this.dataGridView.ReadOnly = true;

this.dataGridView.AutoGenerateColumns = false;
DataGridViewTextBoxColumn column;

column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "Id";
column.HeaderText = "Id";
this.dataGridView.Columns.Add(column);

column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "UserName";
column.HeaderText = "UserName";
this.dataGridView.Columns.Add(column);

this.dataGridView.DataSource = myList;
我还尝试在我的
IBindingList
AllowNew
上返回
true
。这没有明显的影响

同样失败的是:

var bindingSource = new BindingSource();
bindingSource.DataSource = myList;
this.dataGridView.DataSource = bindingSource;
问题是,我如何告诉绑定机制识别我的
数据项

(谢谢)

更新1:

我做了一个小测试项目,显示了以下问题:

public partial class Form1: Form {
    public Form1() {
        InitializeComponent();
    }

    class DataItem: INotifyPropertyChanged {
        private int _id;
        public int Id {
            get {
                return _id;
            }
            set {
                if (value != _id) {
                    _id = value;
                    OnPropertyChanged("Id");
                }
            }
        }

        private string _userName;
        public string UserName {
            get {
                return _userName;
            }
            set {
                if (value != _userName) {
                    _userName = value;
                    OnPropertyChanged("UserName");
                }
            }
        }

        private void OnPropertyChanged(string propertyName) {
            var handler = PropertyChanged;
            if (handler != null) {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

    /// Make a list of type DataItem or object...
    //BindingList<object> list = new BindingList<object>() {
    BindingList<DataItem> list = new BindingList<DataItem>() {
        //new DataItem() {
        //    Id = 1,
        //    UserName = "testuser"
        //}
    };
    private void Form1_Load(object sender, EventArgs e) {
        DataGridView dataGridView = new System.Windows.Forms.DataGridView();
        dataGridView.Size = new Size(this.Width-20, this.Height-30);

        dataGridView.AutoGenerateColumns = true;
        DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
        column.DataPropertyName = "Id";
        column.HeaderText = "Id";
        dataGridView.Columns.Add(column);

        this.Controls.Add(dataGridView);



        dataGridView.DataSource = list;

        list.Add( 
            new DataItem() {
                Id = 3,
                UserName = "admin"
            }
        );

        // Make some modifications on the data...
        (new System.Threading.Thread( state => {
            System.Threading.Thread.CurrentThread.IsBackground = true;

            System.Threading.Thread.Sleep(2000);
            this.Invoke( (Action)( () => {
                list.Add(new DataItem() {
                    Id = 2,
                    UserName = "guest"
                });
            } ) );

            System.Threading.Thread.Sleep(2000);
            this.Invoke( (Action)( () => {
                DataItem user = (list.First( obj => ((DataItem)obj).Id == 3 )) as DataItem;
                user.UserName = "Administrator";
            } ) );
        })).Start();
    }
}
公共部分类表单1:表单{
公共表格1(){
初始化组件();
}
类数据项:INotifyPropertyChanged{
私人内部id;
公共整数Id{
得到{
返回_id;
}
设置{
如果(值!=\u id){
_id=值;
OnPropertyChanged(“Id”);
}
}
}
私有字符串\u用户名;
公共字符串用户名{
得到{
返回_用户名;
}
设置{
如果(值!=\u用户名){
_用户名=值;
OnPropertyChanged(“用户名”);
}
}
}
私有void OnPropertyChanged(字符串propertyName){
var handler=PropertyChanged;
if(处理程序!=null){
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共事件属性更改事件处理程序属性更改;
}
///创建数据项或对象类型的列表。。。
//BindingList=新的BindingList(){
BindingList=新的BindingList(){
//新数据项(){
//Id=1,
//UserName=“testuser”
//}
};
私有void Form1\u加载(对象发送方、事件参数e){
DataGridView DataGridView=new System.Windows.Forms.DataGridView();
dataGridView.Size=新的大小(this.Width-20,this.Height-30);
dataGridView.AutoGenerateColumns=true;
DataGridViewTextBoxColumn=新DataGridViewTextBoxColumn();
column.DataPropertyName=“Id”;
column.HeaderText=“Id”;
dataGridView.Columns.Add(column);
this.Controls.Add(dataGridView);
dataGridView.DataSource=list;
列表。添加(
新数据项(){
Id=3,
UserName=“admin”
}
);
//对数据进行一些修改。。。
(新的System.Threading.Thread(状态=>{
System.Threading.Thread.CurrentThread.IsBackground=true;
系统线程线程睡眠(2000);
this.Invoke((操作)(()=>{
添加(新数据项(){
Id=2,
UserName=“guest”
});
} ) );
系统线程线程睡眠(2000);
this.Invoke((操作)(()=>{
DataItem user=(list.First(obj=>((DataItem)obj.Id==3))作为DataItem;
user.UserName=“管理员”;
} ) );
})).Start();
}
}

如果列表的类型为
BindingList
,则其工作正常。如果类型为
BindingList
,则仅当初始化
数据源时列表不为空时,数据绑定才会工作。数据绑定将从查看列表项开始,尝试获取其属性,但是对于空列表,它将获取其所有信息来自列表项的
类型
。如果使用空的
绑定列表
,数据绑定无法发现任何属性的原因是
对象
没有可绑定的属性

要完全确保
DataCollection
类正确支持绑定,即使是空的,也要实现
ITypedList
接口。它包括方法
GetItemProperties()
,它允许您明确说明哪些属性是可绑定的。在此方法中,您可以使用以下命令返回
数据项上的属性

return TypeDescriptor.GetProperties(typeof(DataItem));

这样,即使集合为空,数据绑定也会知道要显示哪些属性。

解决方案非常简单,我就是找不到