加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 01:39:22 所属栏目:百科 来源:网络整理
导读:我有一个特殊的问题,实现我自己的集合,应该支持IBindingList. 我有一个特定数据类(DataItem)的集合类(DataCollection).该集合实现接口IBindingList,IList,IList DataItem并且DataItem实现了INotifyPropertyChanged(并具有数据绑定的公共属性). 当我尝试通过
我有一个特殊的问题,实现我自己的集合,应该支持IBindingList.

我有一个特定数据类(DataItem)的集合类(DataCollection).该集合实现接口IBindingList,IList,IList< DataItem>并且DataItem实现了INotifyPropertyChanged(并具有数据绑定的公共属性).

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

我也尝试过,使用BindingList< DataItem>绑定我的DataItems.在这种情况下,即使列表在设置DataSource时为空,网格也能正常工作.另一方面,如果我使用BindingList< object> (但与内容相同的DataItems)行为与我的DataCollection一样错误.我想问题是,如果在绑定时列表为空,则数据绑定无法正确检测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;

问题是,我如何告诉绑定机制识别我的DataItems?

(谢谢)

更新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();
    }
}

如果列表的类型是BindingList< DataItem>它工作正常.如果类型是BindingList< object>它仅在初始化DataSource时列表不为空时才有效.

解决方法

数据绑定将首先查看列表项以尝试获取其属性,但是对于空列表,它将从列表项的类型中获取其所有信息.如果您使用空BindingList< object>数据绑定无法发现任何属性的原因该对象没有可绑定的属性.

要完全确保DataCollection类正确支持绑定(即使为空),请实现ITypedList接口.它包含方法GetItemProperties(),它允许您显式声明哪些属性是可绑定的.在此方法中,您可以使用以下命令返回DataItem上的属性:

return TypeDescriptor.GetProperties(typeof(DataItem));

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读