简体   繁体   中英

Populate DataGridView

I have a DataGridView on Form1 . I need to fill the Dgv with a specific method in other classes/methods, but I can't access it , I need help please.

The name of the DataGridView is DataConsole .

Here is the method I need to use to popularize Dgv:

public static void addrow(string modo, string acao, string info, int tipo_msg, string msg,
                                    string extra, int tipo_extra, string origem, string fase_origem, string metodo)
        {
            int idrow = DataConsole.Rows.Add();

            using (DataGridViewRow row = DataConsole.Rows[idrow])
            {
                row.Cells["dg_data"].Value = DateTime.Now;
                row.Cells["dg_modo"].Value = modo;
                row.Cells["dg_acao"].Value = acao;
                row.Cells["dg_info"].Value = info;

                row.Cells["dg_tipo"].Value = tipo_msg;
                row.Cells["dg_msg"].Value = msg;
                row.Cells["dg_extra"].Value = extra;
                row.Cells["dg_TipoExtra"].Value = tipo_extra;
                row.Cells["dg_origem"].Value = origem;
                row.Cells["dg_FaseOrigem"].Value = fase_origem;
                row.Cells["dg_metodo"].Value = metodo;
            }
        }

You can use DataSource for that, its easy and more faster then adding or updating any GrdiRow to grid. More details about DataSource can be found here . Also I would suggest you to Get and set Data via DataSource itself.

Option 1

Add a parameter for the DataConsole of DataGridView type in the class method and Pass it as an argument in the caller.

public static void addrow(
    DataGridView dgv,
    string modo, 
    string acao, 
    string info, 
    int tipo_msg, 
    string msg,
    string extra, 
    int tipo_extra, 
    string origem, 
    string fase_origem, 
    string metodo)
{
    var idrow = dgv.Rows.Add();
    var row = dgv.Rows[idrow];

    row.Cells["dg_data"].Value = DateTime.Now;
    row.Cells["dg_modo"].Value = modo;
    row.Cells["dg_acao"].Value = acao;
    row.Cells["dg_info"].Value = info;

    row.Cells["dg_tipo"].Value = tipo_msg;
    row.Cells["dg_msg"].Value = msg;
    row.Cells["dg_extra"].Value = extra;
    row.Cells["dg_TipoExtra"].Value = tipo_extra;
    row.Cells["dg_origem"].Value = origem;
    row.Cells["dg_FaseOrigem"].Value = fase_origem;
    row.Cells["dg_metodo"].Value = metodo;
}

Then you can call the method from frm_Console as follows:

public partial class frm_Console : Form
{
//...

    private void TheCaller()
    {
        addrow(DataConsole, //the rest of the parameters....);
    }
}

Option 2

Set the Modifiers property of the DataConsole control to Public or Internal, find it's container Form in the class method, and access it:

public static void addrow(
    string modo, 
    string acao, 
    string info, 
    int tipo_msg, 
    string msg,
    string extra, 
    int tipo_extra, 
    string origem, 
    string fase_origem, 
    string metodo)
{
    var f = Application.OpenForms.OfType<frm_Console>().FirstOrDefault();

    if (f == null) return;

    var idrow = f.DataConsole.Rows.Add();
    var row = f.DataConsole.Rows[idrow];

    row.Cells["dg_data"].Value = DateTime.Now;
    row.Cells["dg_modo"].Value = modo;
    row.Cells["dg_acao"].Value = acao;
    //...etc.
}

Option 3

Declare a static variable in the method's class of DataGridView type, set it to DataConsole in frm_Console construcor.

public class SomeClass
{
    public static DataGridView DataConsol;

    public static void addrow(
        string modo, 
        string acao, 
        string info, 
        int tipo_msg, 
        string msg,
        string extra, 
        int tipo_extra, 
        string origem, 
        string fase_origem, 
        string metodo)
    {
        if (DataConsol == null) return; //or throw an exception...

        var idrow = DataConsol.Rows.Add();
        var row = DataConsol.Rows[idrow];

        row.Cells["dg_data"].Value = DateTime.Now;
        row.Cells["dg_modo"].Value = modo;
        row.Cells["dg_acao"].Value = acao;
        //...etc.
    }       
}

public partial class frm_Console : Form
{
    public frm_Console()
    {
        InitializeComponent();

        SomeClass.DataConsol = this.DataConsole;
    }
//...
}

Option 4

Keep the DataConsole-Related routines in the frm_Console where the control belongs.

You are having these problems, because you are not using a DataSource to populate the DataGridView (DGV). This will not only make it more difficult to show the data, but also to fetch changed data.

Every row in your DGV will be of the same type:

class RowData
{
    public string Modo {get; set;}
    public string Acao {get; set;}
    ...
}

Use Visual Studio Designer to create the DGV and a BindingSource. Let the BindingSource show types of RowData . This will automatically create all columns for you, which you can manually change or delete if you want.

You can also do this by hand in your code:

DataGridView dataConsole = new DataGridView();
DataGridViewColumn columnModo = new DataGridViewColumn(){...}
DataGridViewColumn columnAcao = new DataGridViewColumn(){...}
... // create other columns

dataConsole.Columns.Add(columnModo);
dataConsole.Columns.Add(columnAcao);
...  // add other columns

Now the important part:

// The data that will be as rows in your table:
BindingList<RowData> dataConsoleContent = new BindingList<RowData>();

Or if you already have some initial data:

List<RowData> initialData = ...
BindingList<RowData> dataConsoleContent = new BindingList<RowData>(initialData);

Tell the DGV that it should show the data that is in the BindingList:

dataConsole.DataSource = dataConsoleContent;

To add a new Row, simply tell dataConsoleContent object to create a new Row:

RowData newRow = dataConsoleContent.AddNew();

// if you have data: just fill it
newRow.Modo = ...
newRow.Acao = ...
...

And tell everyone who shows this BindingList that it is changed:

dataConsoleContent.ResetBinding().

If a User edits the DataGridView, adds new Rows, changes cell content, or delete rows, the result is automatically in the BindingList:

private void OnButtonFinishedEditing_Clicked(object sender, ...)
{
    IEnumerable<DataRow> allDataRows = this.dataConsoleContent;
    ProcessEditedData(allDatarows);
}

Using ResetBinding is not very efficient, because it will refresh the complete DataGridView. If you regularly will change data programmatically (so not changed by the operator), then your DataRow needs to implement INotifyPropertyChanged. For an example see How to: Raise Change Notifications Using a BindingSource and the INotifyPropertyChanged Interface

This is some work. Luckily there are several nuget packages where this has been done for you. One of my favorites is Nuget Equin.ApplicationFramework.BindingListView . It does all the DataSource work for you, plus it has automatic sorting by clicking on the column headers. Another different feature is that it is easy to filter the shown element without removing elements from the DataSource:

List<Customer> customers = GetCustomers();
BindingListView<Customer> view = new BindingListView<Customer>(customers);
dataGridView1.DataSource = view;

In the grid you can now sort by clicking on the headers. The sort order is done automatically, as well as adjusting the "glyph" on the header which shows you the sort direction. You can programmatically sort the view using the ApplySort method.

Show only old Customers:

DateTime dateLimit = DateTime.Now - TimeSpan.FromYears(65);
view.ApplyFilter(customer => customer.Birthday < dateLimit});

And presto, you'll only see the elderly Customers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM