Link to home
Start Free TrialLog in
Avatar of ichikuma
ichikumaFlag for United States of America

asked on

Linking two DataGridView controls that aren't data bound

I have a need to create two DataGridView controls on a form that contain the exact same data where the left grid is programmatically populated.  The requirement is that the right grid can be sorted differently than the left grid by clicking on the column headers.  I'm having two issues with this:

1.  Is there a way to "clone" one grid to equal another grid so the data will automatically copied to the second grid when the left grid is being populated?  I tried this but it didn't work:
dataGridViewRight = dataGridViewLeft
The strange thing is, the data seems to be the same between the two grids but nothing is displayed in the right grid.  Is there a way to display the data after you set one grid equal to the other grid?
2.  The left grid will be constantly upgraded, it's a scoring grid.  How would I handle if the data in the left grid changes and the right grid is sorted differently?  I tried capturing the left grid CellChanged event but I have no idea where the cell is in the right grid.

Is there anyway to do this?
Avatar of _Katka_
_Katka_
Flag of Czechia image

Hi, it would really be easier to data bound both grids, via BindingSource component. They'll have one context, and it will accomplish exactly what you want.

You can bound a List<> for example, so no DataSets are needed.

bindingSource.DataSource = myList;
dataGridView1.DataSource = bindingSource;
dataGridView2.DataSource = bindingSource;

Really easy, what is the reason you can't use a data-binding ?

regards,
Kate
Avatar of ichikuma

ASKER

Hi Kate,

Thanks for the response.  The way the system works is, I get a feed from an outside source that gives me data in a text format.  My grid view has a max of maybe 50 rows.  The feed I get, could update one of those rows so I never really have the complete data, it's fed to me randomly a row at a time so I can't really build the grids with a datasource and since the data is being streamed real time, I'm not sure how to overcome this problem.  Any ideas?

Thanks again,

Craig
Ok, can't you just update data ? As in, having the List<MyData> hooked to a datasource, and when the new textual data come.. parse them, update the list, and the refresh the datasource (or grid). So instead of changing rows, you change "rows" in your list, and make a refresh. No need to rehook your data.

regards,
Kate

Hmm...that seems feasable and as a test I bound the left grid to a List and then set the right grids datasource = left grid datasource. So my data shows up in each list like I want. It doesn't look like this will work though because I can't sort any of the columns. Also, one other caveat, when the data comes in and I manually update the grid, I also need to format some of the cells to show who is moving up the scoreboard. I'm don't know how I could update cells by providing a List.

Here is the code I'm using and the columns don't sort, am I doing something wrong or not setting a property correctly?

Thanks again,

Craig
namespace DataGridViewSample
{
    public class MyDataList
    {
        private string _column1 = string.Empty;
        public String Column1
        {
            get
            {
                return _column1;
            }
            set
            {
                _column1 = value;
            }
        }

        private string _column2 = string.Empty;
        public String Column2
        {
            get
            {
                return _column2;
            }
            set
            {
                _column2 = value;
            }
        }

        public MyDataList(string column1, string column2)
        {
            this.Column1 = column1;
            this.Column2 = column2;
        }
    }

    public partial class Form1 : Form
    {
        private List<MyDataList> dataList = new List<MyDataList>();

        public Form1()
        {
            InitializeComponent();
            dataList.Add(new MyDataList("Column1", "Column2"));
            dataList.Add(new MyDataList("Column10", "Column20"));

            dataGridViewLeft.DataSource = dataList;
            
            
            dataGridViewRight.DataSource = dataGridViewLeft.DataSource;
        }
    }
}

Open in new window

I found that I can use a DataTable and that allows sorting of the columns but if I sort one grid, it sorts the other grid as well, any way to disconnect so they can be sorted independently of each other?

I posted the the code that I'm using.  Now all I have to do is "disconnect" the column sorting and figure out how to change the cell formatting using the datatable.
public Form1()
        {
            InitializeComponent();
            dataList.Add(new MyDataList2("Column1", "Column2"));
            dataList.Add(new MyDataList2("Column10", "Column20"));

            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("Column 1", typeof(string));
            dataTable.Columns.Add("Column 2", typeof(string));

            foreach (MyDataList2 data in dataList)
            {
                dataTable.Rows.Add(new object[] { data.Column1, data.Column2 });
            }

            dataGridViewLeft.DataSource = dataTable;


            dataGridViewRight.DataSource = dataGridViewLeft.DataSource;
        }

Open in new window

Seems I got everything working except for modifying the format of the cells.  If you have any ideas on that I would certainly be attentive to see how.  That's one thing I can't seem to find searching.

Thanks again for all your help and giving me the insight to seek another solution.  I've listed the code I used to get it working, if you see any inherent pitfalls that I haven't seen please let me know.
    public partial class Form1 : Form
    {
        private List<MyDataList2> dataList = new List<MyDataList2>();
        DataTable dataTable = new DataTable();

        public Form1()
        {
            InitializeComponent();
            dataList.Add(new MyDataList2("Column1", "Column2"));
            dataList.Add(new MyDataList2("Column10", "Column20"));

            dataTable.Columns.Add("Column 1", typeof(string));
            dataTable.Columns.Add("Column 2", typeof(string));

            foreach (MyDataList2 data in dataList)
            {
                dataTable.Rows.Add(new object[] { data.Column1, data.Column2 });
            }

            dataGridViewLeft.DataSource = dataTable;
            dataGridViewRight.DataSource = dataTable.Copy();
        }

        private void btnAddRecord_Click(object sender, EventArgs e)
        {
            dataTable.Rows.Add(new object[] { "Hello", "Goodbye" });

            //Get the sort order of the grid so we can set it after the new data is added
            DataGridViewColumn c = this.dataGridViewRight.SortedColumn;
            SortOrder order = dataGridViewRight.SortOrder;

            //Remap the data table to the right grid
            dataGridViewRight.DataSource = dataTable.Copy();

            if (c != null)
            {
                DataGridViewColumn newColumn = dataGridViewRight.Columns[c.Name];
                ListSortDirection sortOrder = new ListSortDirection();
                sortOrder = ListSortDirection.Ascending;

                if (order == SortOrder.Descending)
                {
                    sortOrder = ListSortDirection.Descending;
                    newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending;
                }

                dataGridViewRight.Sort(newColumn, sortOrder);
                newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
                if (sortOrder == ListSortDirection.Descending)
                {
                    newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending;
                }
            }
        }
    }

Open in new window

This should be the easy part. You just need to hook CellFormatting event <see code snippet>.

regards,
Kate
private void dataGridViewLeft_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    // filter for which column
    if (e.ColumnIndex == 0) // 'Column 1' in this case
    {
        switch (e.Value.ToString())
        {
            case "Column1":
              e.Value = "Something";
              break;

            case "Column10":
              e.Value = "Something else";
              break;
        }
    }
}

Open in new window

I think I'm back where I started, if I sort the right datagrid and I need to format the data in the left grid, how do I know which cell in the right grid I need to format?  Is there a way to link the cell formatting to the datatable?
ASKER CERTIFIED SOLUTION
Avatar of _Katka_
_Katka_
Flag of Czechia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I might have a solution, the first column of my data is unique in the datagridview so maybe I can get the unique value from the left grid and get it's formatting, then in the right grid, find the row and add the formatting, that should work right?

Thanks again for all your help...