This is a migrated thread and some comments may be shown as answers.

Dinamically changing a cell's backcolor

9 Answers 304 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Alexandre
Top achievements
Rank 1
Alexandre asked on 17 Feb 2011, 09:24 PM
I'm working on a solution wich receives events that represent data from stock exchange.
I receive the data and list the quotes within the radgridview. What I want is to change the backcolor of a cell for around 500ms, to blue, if the price rises, red if it goes down and do nothing if the prices remains the same.
I have read the topics, and conditional formatting is not possible, because i don't have a static value to trigger the color change. Then I tried, as some topics suggest, changing the backcolor of the cell using the CellFormatting Event. However, when the values in the cell change, the event triggered is CellValueChanged, not CellFormatting. I was wondering if there is a way for me to raise the CellFormatting after I receive a CellValueChanged.

Thanks,

Alexandre

9 Answers, 1 is accepted

Sort by
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 17 Feb 2011, 10:07 PM
Hello,

CellFormatting would be the way to go with this. You can get a cell or row to cause the formatting event to fire by calling the InvalidateRow method
Private Sub RadGridView1_CellValueChanged(ByVal sender As System.Object, ByVal e As Telerik.WinControls.UI.GridViewCellEventArgs) Handles RadGridView1.CellValueChanged
    ' do something
    e.Row.InvalidateRow()
End Sub

Hope that helps, but let me know if you have any questions
Richard
0
Alexandre
Top achievements
Rank 1
answered on 18 Feb 2011, 02:42 PM
Thanks, Richard, it really changes the cell color.
 However, I needed that, when the value in a cell changes, the cell highlights blue and then turn it back to the original color after a period of time. I tried using the e.Row.InvalidateRow(), but it only changes the backcolor, and I still need to click on the cell to see the new backcolor.
Besides, how could I make the cell turn back again to the original backcolor after, let's say 500ms? I guess I should use a separate thread, but again, how could I invoke the CellFormatting Event after the time's up?

So the 2 issues I can't handle are:
- Highlighting the cells when the value changes (without having to click on them)
- Makes the backcolor turn back after a time interval

Thanks,
Alexandre
0
Richard Slade
Top achievements
Rank 2
answered on 18 Feb 2011, 03:31 PM
hello,

Well, to change the back color to the original value you can set
e.CellElement.ResetValue(LightVisualElement.BackColorProperty);
indeed, this is required. (refer to CellFormatting docs).

However, now knowing a little bit more about what you would like to do, makes me think that this may not be the best way. The CellFormatting event is fired very often due to the unique UI Virtualization mechanism of the RadGridView (read more about the logical vs visual structure of RadGridView here).

The issue will be the cell changing to blue for a period of time. I'm wondering if the CellPaint event might be more appropriate to your needs. Perhaps you can tell me more about your grid and if I can help, i will.

For exmaple: Will the user be adding, editing, sorting etc.. Will there be more than a page of data on the screen (scrollable).
Let me know. To be honest, I haven't come across this situation previously, but it sounds like an interesting one to try and tackle.
Richard
0
Alexandre
Top achievements
Rank 1
answered on 21 Feb 2011, 01:38 PM
Hello Richard,
The grid i'm working with has around 100 rows of data, with 10 columns. The user must be able to sort the rows and whenever a cell changes its value, it must get a blue backcolor for 500ms  and the turn it back to the original backcolor (The table enables alternating rowcolor).
Is it possible combining the CellFormatting and the CellPaint events? What should be the better way to achieve my needs?

Thank you, I really appreciate your help.
Alexandre.
0
Richard Slade
Top achievements
Rank 2
answered on 21 Feb 2011, 02:18 PM
Hello,

I will have a look into this for you as currnetly I am not familiar with a system that will consistantly work for this. I'll come back to you as soon as I can.
Regards,
Richard
0
Richard Slade
Top achievements
Rank 2
answered on 21 Feb 2011, 03:26 PM
Hello,

Just to let you know that I am still looking at this, but I thought I'd give you something in the meantime. It doesn't do exactly what you want, but it's a start.
The values change and it will alter the cell colour depending on if it goes up or down. I'll keep looking to see if it is possible to do exactly what you need, though it may take me some time.

In the meantime, I hope this helps a little

EDIT// Code removed - incompatible with sorting.
0
Richard Slade
Top achievements
Rank 2
answered on 21 Feb 2011, 06:55 PM
Hello again,

Ok, I have something very basic working. It works on the principal that you have the information to say if the data has gone up or down in the data source. Every 5 seconds the data refreshes, and the cell will flash the required colour for 500ms.

Each time the whole data source is refreshed, and the data binding complete event is fired and the cell formatting is forced.

Have a go with this anyway and let me know how it looks for you.

Designer File
partial class Form1
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components;
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.components = new System.ComponentModel.Container();
        this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
        this.radGridView1 = new Telerik.WinControls.UI.RadGridView();
        this.timer1 = new System.Windows.Forms.Timer(this.components);
        ((System.ComponentModel.ISupportInitialize)(this.radGridView1)).BeginInit();
        this.SuspendLayout();
        // 
        // backgroundWorker1
        // 
        this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
        // 
        // radGridView1
        // 
        this.radGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.radGridView1.Location = new System.Drawing.Point(0, 0);
        this.radGridView1.Name = "radGridView1";
        this.radGridView1.Size = new System.Drawing.Size(284, 262);
        this.radGridView1.TabIndex = 0;
        this.radGridView1.Text = "radGridView1";
        this.radGridView1.CellFormatting += new Telerik.WinControls.UI.CellFormattingEventHandler(this.radGridView1_CellFormatting);
        this.radGridView1.DataBindingComplete += new Telerik.WinControls.UI.GridViewBindingCompleteEventHandler(this.radGridView1_DataBindingComplete);
        // 
        // timer1
        // 
        this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
        // 
        // Form1
        // 
        this.ClientSize = new System.Drawing.Size(284, 262);
        this.Controls.Add(this.radGridView1);
        this.Name = "Form1";
        this.Load += new System.EventHandler(this.Form1_Load);
        ((System.ComponentModel.ISupportInitialize)(this.radGridView1)).EndInit();
        this.ResumeLayout(false);
    }
    #endregion
    private System.ComponentModel.BackgroundWorker backgroundWorker1;
    private Telerik.WinControls.UI.RadGridView radGridView1;
    private System.Windows.Forms.Timer timer1;
}

Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls.UI;
  
  
    public partial class Form1 : Form
    {
        private Boolean m_Continue;
        private BindingList<MyObject> m_List = new BindingList<MyObject>();
        private delegate void ResetBindingCallback();
  
        public Form1()
        {
            InitializeComponent();
        }
  
        private void Form1_Load(object sender, EventArgs e)
        {
            m_Continue = true;
            m_List.Add(new MyObject(1.0M, "Object 1", "Equal"));
            m_List.Add(new MyObject(2.5M, "Object 2", "UP"));
            m_List.Add(new MyObject(3.6M, "Object 3", "DOWN"));
  
  
            this.radGridView1.AutoGenerateColumns = true;
            this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.None;
            this.radGridView1.ReadOnly = true;
  
            this.radGridView1.DataSource = m_List;
            this.backgroundWorker1.RunWorkerAsync();
  
            this.radGridView1.Columns["ValueIs"].IsVisible = false;
            using (this.radGridView1.DeferRefresh())
            {
                foreach (GridViewDataColumn column in this.radGridView1.Columns)
                { column.BestFit(); }            
            }
        }
  
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (m_Continue == true)
            {
                // Simulate getting new data source from a background worker
                // include how the price has changed in the source
                m_List[0].Price = m_List[0].Price + 1;
                m_List[0].Name = "Object 1";
                m_List[0].ValueIs = "UP";
                m_List[1].Price = m_List[1].Price - 1;
                m_List[1].Name = "Object 2";
                m_List[1].ValueIs = "DOWN";
                m_List[2].Price = m_List[2].Price + 1;
                m_List[2].Name = "Object 3";
                m_List[2].ValueIs = "UP";
                Invoke(new ResetBindingCallback(ResetBinding));
                // change every 3 seconds
                System.Threading.Thread.Sleep(5000);
                m_List[0].Price = m_List[0].Price - 1;
                m_List[0].Name = "Object 1";
                m_List[0].ValueIs = "DOWN";
                m_List[1].Price = m_List[1].Price + 2;
                m_List[1].Name = "Object 2";
                m_List[1].ValueIs = "UP";
                m_List[2].Price = m_List[2].Price - 2;
                m_List[2].Name = "Object 3";
                m_List[2].ValueIs = "DOWN";
                Invoke(new ResetBindingCallback(ResetBinding));
                System.Threading.Thread.Sleep(5000);
            }
        }
  
        private void ResetBinding()
        {
            if (m_Continue) 
            {
                this.radGridView1.DataSource = null;
                this.radGridView1.DataSource = m_List;
                this.radGridView1.Columns["ValueIs"].IsVisible = false;
            }
        }
  
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            m_Continue = false;
        }
  
  
        private void radGridView1_DataBindingComplete(object sender, GridViewBindingCompleteEventArgs e)
        {
            for (int i = 0; i <= this.radGridView1.Rows.Count - 1; i++)
            {
                this.radGridView1.Rows[i].Tag = true;
                this.radGridView1.TableElement.Update(GridUINotifyAction.StateChanged);
            }
            this.timer1.Interval = 500;
            this.timer1.Start();
        }
  
  
        private void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
        {
            if (Convert.ToBoolean(e.CellElement.RowInfo.Tag) == true)
            {
                if (e.CellElement.ColumnInfo.Name == "Price" && e.CellElement.Value != null)
                {
                    if (e.CellElement.RowInfo.Cells["ValueIs"].Value.ToString() != null)
                    {
                        switch (e.CellElement.RowInfo.Cells["ValueIs"].Value.ToString())
                        {
                            case "UP":
                                e.CellElement.BackColor = Color.Blue;
                                e.CellElement.DrawFill = true;
                                e.CellElement.NumberOfColors = 1;
                                break;
                            case "DOWN":
                                e.CellElement.BackColor = Color.Red;
                                e.CellElement.NumberOfColors = 1;
                                e.CellElement.DrawFill = true;
                                break;
                            default:
                                e.CellElement.ResetValue(LightVisualElement.BackColorProperty);
                                e.CellElement.ResetValue(LightVisualElement.NumberOfColorsProperty);
                                e.CellElement.ResetValue(LightVisualElement.DrawFillProperty);
                                break;
                        }
                    }
                    else
                    {
                        e.CellElement.ResetValue(LightVisualElement.BackColorProperty);
                        e.CellElement.ResetValue(LightVisualElement.NumberOfColorsProperty);
                    }
                }
                else
                {
                    e.CellElement.ResetValue(LightVisualElement.BackColorProperty);
                    e.CellElement.ResetValue(LightVisualElement.NumberOfColorsProperty);
                }
            }
            else
            {
                e.CellElement.ResetValue(LightVisualElement.BackColorProperty);
                e.CellElement.ResetValue(LightVisualElement.NumberOfColorsProperty);
            }
        }
  
        private void timer1_Tick(object sender, EventArgs e)
        {
  
            for (int i = 0; i <= this.radGridView1.Rows.Count - 1; i++)
            {
                this.radGridView1.Rows[i].Tag = false;
                this.radGridView1.TableElement.Update(GridUINotifyAction.StateChanged);
            }
            this.timer1.Stop();
        }
  
    }
  
    public class MyObject
    {
        public MyObject() { }
  
        public MyObject(decimal price, string name, string valueIs)
        {
            this.Price = price;
            this.Name = name;
            this.ValueIs = valueIs;
        }
  
        public decimal Price
        { get; set; }
  
        public string Name
        { get; set; }
  
        public string ValueIs
        { get; set; }
    }

regards,
Richard
0
Alexandre
Top achievements
Rank 1
answered on 21 Feb 2011, 08:16 PM
Awesome, man!! Thank you very much!
You're a telerik freak!

regards,
Alexandre
0
Richard Slade
Top achievements
Rank 2
answered on 21 Feb 2011, 08:37 PM
:oD
Glad that it has helped you!
All the best
Richard
Tags
GridView
Asked by
Alexandre
Top achievements
Rank 1
Answers by
Richard Slade
Top achievements
Rank 2
Alexandre
Top achievements
Rank 1
Share this question
or