Alternative to DataGridView DataBindingComplete Event

落花浮王杯 提交于 2019-12-31 04:57:14

问题


As stated here the DataBindingComplete event for a DataGridView is fired whenever the contents of the data source change, or a property such as DataSource changes. This results in the method being called multiple times.
I am currently using the DataBindingComplete event to do some visual formatting to my form. For example, I make the text in the first column (column 0) appear as Row Headers and then hide that column (see code below).

private void grdComponents_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    { 
        foreach (DataGridViewRow row in grdComponents.Rows)
        {
            row.HeaderCell.Value = row.Cells[0].Value.ToString();
        }
        grdComponents.Columns[0].Visible = false;

        // do more stuff...
    }

It is unnecessary to execute this code more than once, and I am looking to put it into a place where that can happen. Unfortunately it didn't work when I added the snippet to the end of my form's Load method (after I set the DataSource of my DataGridView), nor did it work in the DataSourceChanged event.


回答1:


The simplest way will be just to execute this code once:

Add a flag like Boolean isDataGridFormatted in your form.

And check it like

private void grdComponents_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{ 
    if (this.isDataGridFormatted )
        return;

    foreach (DataGridViewRow row in grdComponents.Rows)
    {
        row.HeaderCell.Value = row.Cells[0].Value.ToString();
    }
    grdComponents.Columns[0].Visible = false;

    // do more stuff...

    this.isDataGridFormatted  = false;         
}

A bit better will be to prepare your DataGridView during the form construction. As I understand your columns won't change during the course of your program but you don't want to initialize everything manually. You could load some dummy one-item(one-row) data during the initialization:

private void Initialize_DataGridView()
{
    // Add dummy data to generate the columns
    this.dataGridView_Items.DataContext = new Item[]{ new Item {Id = 5, Value = 6}};

    // Make your formatting
    foreach (DataGridViewRow row in grdComponents.Rows)
    {
        row.HeaderCell.Value = row.Cells[0].Value.ToString();
    }

    grdComponents.Columns[0].Visible = false;

    // Reset the dummy data
    this.dataGridView_Items.DataContext = null; // Or new Item[]{};
}

...
public MyForm()
{
    Initialize();

    this.Initialize_DataGridView();   
}

I am not sure that exactly such code will work with dataGridView but it is close enough.

Of course an event would have been a nearly ideal solution but there's hardly any that deals with successful autogeneration of columns http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview_events(v=vs.110).aspx except the AutoGenerateColumnChanged but that is not what we need.

While it is possible to use the ColumnAdded - it will probably execute only once foreach of the autogenerated column, the actual implementation could become an overkill and will be even less direct than already mentioned approaches.

If you will have some time and desire you could create your own DataGridView derived class, take Boolean isDataGridFormatted from your form and implement all the initialization(or event hooking) inside the custom DataGridView.




回答2:


Yes, you can use DataSourceChanged event, but be aware, that it occurs only when data source is changed. Additionally, DataBindingComplete offers you information why it has happend - through e.ListChangedType:

Reset = 0,//     Much of the list has changed. Any listening controls should refresh all their data from the list.
ItemAdded = 1,//     An item added to the list
ItemDeleted = 2,//     An item deleted from the list.
ItemMoved = 3,//     An item moved within the list.
ItemChanged = 4,//     An item changed in the list.
PropertyDescriptorAdded = 5,//     A System.ComponentModel.PropertyDescriptor was added, which changed the schema.
PropertyDescriptorDeleted = 6,//     A System.ComponentModel.PropertyDescriptor was deleted, which changed the schema.
PropertyDescriptorChanged = 7//     A System.ComponentModel.PropertyDescriptor was changed, which changed the schema.

According to this answer: https://social.msdn.microsoft.com/forums/windows/en-us/50c4f46d-c3b8-4da7-b08f-a751dca12afd/databindingcomplete-event-is-been-called-twice the whole thing happens because you don't have DataMember property set in your dataGridView. And you can set it only if you want to set particular table from database which is set as your DataSource of dataGridView. Other way - throws an exception.



来源:https://stackoverflow.com/questions/24329964/alternative-to-datagridview-databindingcomplete-event

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