Home Forums WinForms controls Xceed Grid for WinForms Using CellValueChanged in a bound grid

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064
    #15054 |

    Hi,

    I would like to “watch” the cell values of one column. When the value of the cell has a certain value the row should change its color. Providing data manually I can attach a CellValueChanged event handler to each data row but when using a bound data source this is not so obvious. It is desired to trigger the event only when the cell value of the certain column changes but if it is not possible triggering the event on row change may do it. I am grateful for any hint.

    twi

    Imported from legacy forums. Posted by twi (had 6746 views)

    User (Old forums)
    Member
    Post count: 23064

    ATM I managed to implement it by using the DataRow CellValueChanged event. Unfortunately it is triggered every time any of the cell values change:

    // in the constructor:
    this.gridControl1.AddingDataRow += new AddingDataRowEventHandler(gridControl1_AddingDataRow);
    this.gridControl1.DataSource = am.getGrid().getDataSet().Tables[“Futures”];

    void gridControl1_AddingDataRow(object sender, AddingDataRowEventArgs e)
    {
    Debug.WriteLine(“void gridControl1_AddingDataRow(object sender, AddingDataRowEventArgs e)”);
    e.DataRow.CellValueChanged += new EventHandler(DataRow_CellValueChanged);
    }

    void DataRow_CellValueChanged(object sender, EventArgs e)
    {
    Xceed.Grid.DataRow r = sender as Xceed.Grid.DataRow;
    if (r.Cells[“state”].Value.ToString().Replace(” “, “”) != “watched”)
    r.BackColor = Color.LightGoldenrodYellow;
    else
    r.BackColor = Color.White;
    }

    Because of frequent changes of cell values which are not in the “state” column the event is raised unnecessarily often. I would prefer to hook my handler to the cell’s ValueChanged event like this:

    void gridControl1_AddingDataRow(object sender, AddingDataRowEventArgs e)
    {
    e.DataRow.Cells[“state”].ValueChanged += new EventHandler(FuturesView_ValueChanged);
    }

    void FuturesView_ValueChanged(object sender, EventArgs e)
    {
    Debug.WriteLine(“Cell Value changed!! ” + sender.ToString());
    Xceed.Grid.DataCell c = sender as DataCell;
    Xceed.Grid.DataRow r = c.ParentRow as Xceed.Grid.DataRow;

    if(c.Value .ToString().Replace(” “, “”) != “watched”)
    r.BackColor = Color.LightGoldenrodYellow;
    else
    r.BackColor = Color.White;
    }

    Unfortunately this does not have any effect at all. Any suggestions?

    Imported from legacy forums. Posted by twi (had 459 views)

    User (Old forums)
    Member
    Post count: 23064

    I recently saw valuechanged problem, since that was one of the possible means to solve my checkbox clicked event, but it wasnt a good one. it is bad because its triggered everytime cell value changes and main prohblem is that this happens on grid load for example !

    so one of dev guys told me another approach for mine problem and i believe it can help you, if not fully then to get you gointg somewhere a bit near to the final solution.
    You could monitor cell EndEdit (or EnterEdit) event this way you should be able to see when someone left the editing of the cell which means it possibly changed the value of it and this event isnt triggered on grid loading.

    cheers

    Imported from legacy forums. Posted by Ma (had 755 views)

    User (Old forums)
    Member
    Post count: 23064

    Hi,

    I am aware of the problem and I am not satisfied with my solution.

    Your suggestion sounds interesting but I don’t support editing cells by user – the values are changed directly in the underlying data source and the grid control is a read-only view. Does the EndEdit event triggers when the value changes or only when you leave the edit mode of a writeable grid control?

    regards

    Imported from legacy forums. Posted by twi (had 867 views)

    User (Old forums)
    Member
    Post count: 23064

    You could use the ValueChanged event available on the Cell class, verify the value of the cell in the event handler, and change the row BackColor accordingly to the value. You can subscribe to this event only for the cells in a specific column, so it will fire only for cells for which you need to check value changes.

    e.g.

    private void Form1_Load(object sender, System.EventArgs e)
    {
    dataRowTemplate1.Cells[ “EmployeeID” ].ValueChanged += new EventHandler(EmployeeID_ValueChanged);
    //then fill the grid with data
    }

    private void EmployeeID_ValueChanged(object sender, EventArgs e)
    {
    Cell cell = sender as Cell;
    if( cell.Value.ToString() == “1” )
    {
    cell.ParentRow.BackColor = Color.Red;
    }

    Imported from legacy forums. Posted by André (had 262 views)

    User (Old forums)
    Member
    Post count: 23064

    Well, if you use

    private void Form1_Load(object sender, System.EventArgs e)
    {
    dataRowTemplate1.Cells[ “EmployeeID” ].ValueChanged += new EventHandler(EmployeeID_ValueChanged);
    //then fill the grid with data
    }

    The column EmployeeID must exist already. I am using a bound data source so I thought about connecting the event handler withe the cell when the row is being added:

    void gridControl1_AddingDataRow(object sender, AddingDataRowEventArgs e)
    {
    e.DataRow.Cells[“state”].ValueChanged += new EventHandler(FuturesView_ValueChanged);
    }

    but that does not trigger the EventHandler, did I overlook something?

    Imported from legacy forums. Posted by twi (had 406 views)

    User (Old forums)
    Member
    Post count: 23064

    to precise the issue:

    After connecting the cells ValueChanged event with the handler, the event triggers after the row is added the first time (thus changing the cell). Later on the changes of the cell do not have any effect which is not logical. I double checked if I muddled up the AddingRow event with the ValueChanged event but everything seems to be setup right.

    Imported from legacy forums. Posted by twi (had 679 views)

    User (Old forums)
    Member
    Post count: 23064

    I’ve tracked down the issue. It is a bug in the implementation of the grid. When you modify rows directly in a bound System.Data.DataTable only the CellValueChanged event of a Xceed.Grid.DataRow is triggered and not the ValueChanged event of a Xceed.Grid.DataCell

    See the following code for proof:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Diagnostics;

    namespace XceedTest
    {
    public partial class Form1 : Form
    {
    DataSet ds;

    public Form1()
    {
    InitializeComponent();

    ds = new DataSet();

    DataTable dt = new DataTable(“pills”);

    dt.Columns.Add(“Id”, typeof(int));
    dt.Columns.Add(“state”, typeof(string));

    dt.Rows.Add(new object[] { 0, “red” });
    dt.Rows.Add(new object[] { 1, “blue” });

    ds.Merge(dt);

    this.gridControl1.AddingDataRow += new Xceed.Grid.AddingDataRowEventHandler(gridControl1_AddingDataRow);
    this.gridControl1.DataSource = ds.Tables[“pills”];
    }

    void gridControl1_AddingDataRow(object sender, Xceed.Grid.AddingDataRowEventArgs e)
    {
    e.DataRow.Cells[“state”].ValueChanged += new EventHandler(Form1_ValueChanged);
    // e.DataRow.CellValueChanged += new EventHandler(DataRow_CellValueChanged); // comment the line above and uncomment this line to check that the row’s event handler reacts on underlying changes
    }

    void DataRow_CellValueChanged(object sender, EventArgs e)
    {
    Debug.WriteLine(“recieved event from data row”);

    Xceed.Grid.DataRow r = sender as Xceed.Grid.DataRow;

    if (r.Cells[“state”].Value.ToString() == “red”)
    r.BackColor = Color.Red;
    else
    r.BackColor = Color.White;
    }

    void Form1_ValueChanged(object sender, EventArgs e)
    {
    Debug.WriteLine(“recieved event from cell”);
    Xceed.Grid.DataCell cell = sender as Xceed.Grid.DataCell;

    if (cell.Value.ToString() == “red”)
    {
    cell.ParentRow.BackColor = Color.Red;
    }
    else
    cell.ParentRow.BackColor = Color.Blue;
    }

    private void button1_Click(object sender, EventArgs e)
    {
    ds.Tables[“pills”].Rows[0][“state”] = “blue”;
    }

    private void button2_Click(object sender, EventArgs e)
    {
    ds.Tables[“pills”].Rows[0][“state”] = “red”;
    }

    }
    }

    Imported from legacy forums. Posted by twi (had 1144 views)

    User (Old forums)
    Member
    Post count: 23064

    You don’t need to use the AddingDataRow event to do this. DataRowTemplate is, as his name indicates, a template. So if you use this :

    private void Form1_Load(object sender, System.EventArgs e)
    {
    dataRowTemplate1.Cells[ “EmployeeID” ].ValueChanged += new EventHandler(EmployeeID_ValueChanged);
    //then fill the grid with data
    }

    each cell of the EmployeeID column will be subscribed to this event handler, and it will work fine.

    When in a bound grid, as soon as the DataSource property is set, the columns are all created, which means that you will be able to use this template to set up the event handler on any column available in the DataSet, and it will actually be subscribed to when filling the grid with data.

    Imported from legacy forums. Posted by André (had 499 views)

    User (Old forums)
    Member
    Post count: 23064

    Investigating this further, the above applies for modification made by a user to a specific cell in the grid.

    However, when changes are made in the DataSet to which the grid is bound, the behavior of the grid is different.

    The reason why the ValueChanged is not raised is that the grid has no mean to know which cell has changed, precisely.

    IBindingList notifies that the item (the record, thus the row) as changed, but nothing indicates which property (cell) has changed on the item.

    So, in this case, the implementation that was chosen was to raise a global row event (CellValueChanged), and not for every cell of the row (ValueChanged ). Raising the ValueChanged for every cell would have been overkilled.

    In your case, one possible solution for this problem would be to keep a buffer of the “old values” for the column that you want to monitor, and if it has changed when a row.CellValueChanged is raised, then perform the task required. However, this may not give you any gain, if you only need to make a single comparison to know to which color you need to change the row. If it requires more calculation, then it may be a valid option.

    Imported from legacy forums. Posted by André (had 7253 views)

Viewing 10 posts - 1 through 10 (of 10 total)
  • You must be logged in to reply to this topic.