Creating a custom collection that can be bound to a DataGrid

浪尽此生 提交于 2019-12-06 11:08:01

You should use BindingList for your collection or implement IBindingList as this will notify back the DataGridView about any changes in the list.

Then implement INotifyPropertyChanged interface for Floor class, this will allow for a TwoWay binding mode between your individual Floor items and the DataGridView.

Eric, you could also do something like this

   public class MyFloorCollection : BindingList<Floor>
            {
                public MyFloorCollection()
                    : base()
                {
                    this.ListChanged += new ListChangedEventHandler(MyFloorCollection_ListChanged);

                }

                void MyFloorCollection_ListChanged(object sender, ListChangedEventArgs e)
                {

                 if (e.ListChangedType == ListChangedType.ItemAdded)
                 {

                    Floor newFloor = this[e.NewIndex] as Floor;

                    if (newFloor != null)
                    {
                        newFloor.HeightChanged += new Floor.HeightChangedEventHandler(newFloor_HeightChanged);
                    }
                  }

                }

                void newFloor_HeightChanged(int newValue, int oldValue)
                {
                    //recaluclate
                }


            }

Of course you can create your own HeightChangedEvent and subscribe to that, that way you dont have to go by property names in an if statement.

So your Floor class will look like this

 public class Floor : INotifyPropertyChanged
        {
            private int _height;

            public int Height
            {
                get { return _height; }
                set 
                {
                    if (HeightChanged != null)
                        HeightChanged(value, _height);

                    _height = value;
                    OnPropertyChanged("Height");

                }
            }




            public int Elevation { get; set; }

            private void OnPropertyChanged(string property)
            {
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs(property));
            }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion

            public delegate void HeightChangedEventHandler(int newValue, int oldValue);
            public event HeightChangedEventHandler HeightChanged;
        }

this way you only have to subscribe to your HeightChanged variable, instead of to PropertyChanged. PropertyChanged will be consumed by the DataGridView to keep a TwoWay binding. I do believe this way is cleaner.

You can also change the delegate and pass the item as the sender.

public delegate void HeightChangedEventHandler(Floor sender, int newValue, int oldValue);

EDIT: To unsubscribe from HeightChanged event you need to override RemoveItem

  protected override void RemoveItem(int index)
        {
            if (index > -1)
                this[index].HeightChanged -= newFloor_HeightChanged;

            base.RemoveItem(index);
        }

Implement IList(Floor), and have your new collection also implement INotifyPropertyChanged interface.

You could try exposing an ObservableCollection<Floor> property on some data containing class. Also, the Floor object would need to implement INotifyPropertyChanged to support two-way binding from the UI.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!