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

RadGridView and use of "Equals" plus CellFormatting

1 Answer 124 Views
GridView
This is a migrated thread and some comments may be shown as answers.
David Storey
Top achievements
Rank 1
David Storey asked on 09 Feb 2010, 12:23 PM
If you compile and run the following snippet, and then follow the steps below;
1. Click add new row (row is defaulted with values);
2. Change the value in the Status column to 4, then hit enter;
The display value for row 5 has been updated with the same values for status and review date.  However the underlying datasource is correctly updated.  The display is different to the underlying object.
This took a while to fathom out (Ive been working with legacy code implementing new features using the Telerik controls).  The problem occurs with the fact that in our ancestor class Equals has been overriden.  In the concrete classes a field called SqlKeyString is overriden and this provides a "key" for the objects to do an equality test.
It therefore looks like the RadGridView is using "Equals" rather than "==", my question is therefore should the RadGridView really be using "==" rather than "Equals"?
My 2nd issue with the gridview, is when adding a new row the CellFormatting doesnt apply to the new row.  When you click a new row in this example a date with value DateTime.MinValue should be displayed as an string.Empty, however the actual value is displayed.
Thanks for your attention,
Dave
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; 
 
namespace TelerikDataGridView 
    #region Form 
    public class Form1 : Form 
    { 
        public Form1() 
        { 
            InitializeComponent(); 
        } 
        /// <summary> 
        /// Required designer variable. 
        /// </summary> 
        private System.ComponentModel.IContainer components = null
 
        /// <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.radGridView1 = new Telerik.WinControls.UI.RadGridView(); 
            ((System.ComponentModel.ISupportInitialize)(this.radGridView1)).BeginInit(); 
            ((System.ComponentModel.ISupportInitialize)(this.radGridView1.MasterGridViewTemplate)).BeginInit(); 
            this.SuspendLayout(); 
            //  
            // 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(905, 285); 
            this.radGridView1.TabIndex = 0; 
            //  
            // Form3 
            //  
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
            this.ClientSize = new System.Drawing.Size(905, 285); 
            this.Controls.Add(this.radGridView1); 
            this.Name = "Form3"
            this.Text = "Form3"
            ((System.ComponentModel.ISupportInitialize)(this.radGridView1.MasterGridViewTemplate)).EndInit(); 
            ((System.ComponentModel.ISupportInitialize)(this.radGridView1)).EndInit(); 
            this.ResumeLayout(false); 
 
        } 
        #endregion 
 
        private Telerik.WinControls.UI.RadGridView radGridView1; 
        protected override void OnLoad(EventArgs e) 
        { 
            base.OnLoad(e); 
            CreateGrid(); 
        } 
        private void CreateGrid() 
        { 
            BindingSource source = new BindingSource(); 
            source.AllowNew = true
            source.AddingNew += new AddingNewEventHandler(source_AddingNew); 
 
            source.DataSource = new MyCollection(); 
            this.radGridView1.MasterGridViewTemplate.AutoGenerateColumns = false
            this.radGridView1.CellFormatting += new CellFormattingEventHandler(radGridView1_CellFormatting); 
            radGridView1.DataSource = source; 
 
            AddTextColumn("FundManagerId""Fund Manager"); 
            AddTextColumn("AssetClassId""Asset Class"); 
            AddTextColumn("ClientOrgId""Client"); 
            AddTextColumn("Status""Status"); 
            AddDateColumn("ReviewDate""Review Date"true); 
 
            radGridView1.MasterGridViewTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;             
        } 
 
        void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e) 
        { 
            if (e.CellElement is GridDateTimeCellElement) 
            { 
                GridDateTimeCellElement cell = e.CellElement as GridDateTimeCellElement; 
                if (cell.IsEditMode) 
                    return
 
                if (((DateTime)cell.Value).Equals(DateTime.MinValue)) 
                    cell.Text = string.Empty; 
                else 
                    cell.Text = string.Format("{0:dd/MM/yyyy}", (DateTime)cell.Value); 
            }  
        } 
        int assetClass = 5; 
        void source_AddingNew(object sender, AddingNewEventArgs e) 
        { 
            e.NewObject = new MyClass(12, 5, assetClass++, 2, DateTime.MinValue); 
        } 
 
        private void AddTextColumn(string field, string header) 
        { 
            AddTextColumn(field, header, false); 
        } 
        private void AddTextColumn(string field, string header, bool readOnly) 
        { 
            GridViewTextBoxColumn column = new GridViewTextBoxColumn(field); 
            column.HeaderText = header; 
            column.ReadOnly = readOnly; 
            radGridView1.MasterGridViewTemplate.Columns.Add(column); 
        } 
        private void AddDateColumn(string field, string header) 
        { 
            AddDateColumn(field, header, false); 
        } 
        private void AddDateColumn(string field, string header, bool readOnly) 
        { 
            GridViewDateTimeColumn dateColumn = new GridViewDateTimeColumn(); 
            dateColumn.BestFit(); 
            dateColumn.FieldName = field; 
            dateColumn.FormatString = "{0:dd/MM/yyyy}"
            dateColumn.HeaderText = header; 
            dateColumn.ReadOnly = readOnly; 
            dateColumn.TextAlignment = ContentAlignment.MiddleCenter; 
            radGridView1.MasterGridViewTemplate.Columns.Add(dateColumn); 
        } 
    } 
    #endregion 
    #region DataSources 
    public class MyClass : InvestmentObject 
    { 
        public MyClass(int client, int fundManager, int assetClass, int status, DateTime statusDate) 
        { 
            FundManagerId = fundManager; 
            AssetClassId = assetClass; 
            ClientOrgId = client; 
            ReviewDate = statusDate; 
            Status = status; 
        } 
        public MyClass(int client, int fundManager, int assetClass) 
            : this(client, fundManager, assetClass, 1, DateTime.Now) 
        { 
 
        } 
        private int _fundManagerId; 
        public int FundManagerId 
        { 
            get { return _fundManagerId; } 
            set 
            { 
                _fundManagerId = value; 
                OnPropertyChanged("FundManagerId"); 
            } 
        } 
 
        private int _assetClassId; 
        public int AssetClassId 
        { 
            get { return _assetClassId; } 
            set 
            { 
                _assetClassId = value; 
                OnPropertyChanged("AssetClassId"); 
            } 
        } 
 
        private int _clientOrgId; 
        public int ClientOrgId 
        { 
            get { return _clientOrgId; } 
            set 
            { 
                _clientOrgId = value; 
                OnPropertyChanged("ClientOrgId"); 
            } 
        } 
 
        private int _status; 
        public int Status 
        { 
            get { return _status; } 
            set 
            { 
                _status = value; 
                OnPropertyChanged("Status"); 
            } 
        } 
 
        private DateTime _reviewDate; 
        public DateTime ReviewDate 
        { 
            get { return _reviewDate; } 
            set 
            { 
                _reviewDate = value; 
                OnPropertyChanged("ReviewDate"); 
            } 
        } 
 
        public override string SqlKeyString 
        { 
            get 
            { 
                return string.Format("FundManagerId={0} and AssetClassId={1} and ClientOrgId={2}" 
                  , FundManagerId, AssetClassId, ClientOrgId); 
            } 
        } 
    } 
 
    public class MyCollection : DataList<MyClass> 
    { 
        public MyCollection() 
        { 
            Add(new MyClass(12, 5, 1)); 
            Add(new MyClass(12, 5, 2)); 
            Add(new MyClass(12, 5, 3)); 
            Add(new MyClass(12, 5, 4)); 
            Add(new MyClass(12, 5, 5)); 
        } 
    } 
    #endregion 
    #region Supporting Data Objects 
    public abstract class DataList<T> : BindingList<T> 
    { 
        public void Sort(Comparison<T> comparer) 
        { 
            ((List<T>)this.Items).Sort(comparer); 
        } 
        public void Sort(IComparer<T> comparer) 
        { 
            ((List<T>)this.Items).Sort(comparer); 
        } 
    } 
    public abstract class InvestmentObject : INotifyPropertyChanged 
    { 
        #region Private Fields 
 
        private DateTime lastModified; 
        private Guid guid; 
        #endregion 
        #region Constructors 
 
        protected InvestmentObject() 
            : base() 
        { 
            lastModified = DateTime.Now; 
            guid = Guid.NewGuid(); 
        } 
        #endregion 
        #region Data Properties 
 
        public DateTime LastModified 
        { 
            get { return lastModified; } 
            protected set { lastModified = value; } 
        } 
 
        public Guid CurrentGUID 
        { 
            get { return guid; } 
            protected set { guid = value; } 
        } 
        #endregion 
 
        public override bool Equals(object obj) 
        { 
            if ((obj != null) && (obj.GetType() == this.GetType())) 
            { 
                InvestmentObject dataAccessObject = obj as InvestmentObject; 
 
                return (dataAccessObject.SqlKeyString == this.SqlKeyString); 
            } 
            else return false
        } 
        public override int GetHashCode() 
        { 
            return (this.GetType().ToString() + SqlKeyString).GetHashCode(); 
        } 
        #region Abstract 
        public abstract string SqlKeyString { get; } 
        #endregion 
        #region INotifyPropertyChanged Members 
 
        public event PropertyChangedEventHandler PropertyChanged; 
 
        protected virtual void OnPropertyChanged(string field) 
        { 
            if (PropertyChanged != null
                PropertyChanged(thisnew PropertyChangedEventArgs(field)); 
        } 
        #endregion 
    } 
    #endregion 
 

1 Answer, 1 is accepted

Sort by
0
Martin Vasilev
Telerik team
answered on 12 Feb 2010, 02:57 PM
Hi David Storey,

Thank you for the provided code. I have managed to reproduce the described issue. As you have already guessed, it is related to the overridden Equals method in your custom object. It seems that RadGridView uses INotifyPropertyChanged.Equals method to distinguish rows. In your case, if you add a row with AssertClassID value that already is taken by another row, your overridden Equals method will return true and RadGridView will consider these two rows equal. We will investigate this situation further and address it if we identify it as a bug. Currently, you have to change your implementation of Equals to return false for different records. 

I have updated your Telerik points for bringing our attention to this. Do not hesitate to contact me again if you have any other questions. 

Best wishes,
Martin Vasilev
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Tags
GridView
Asked by
David Storey
Top achievements
Rank 1
Answers by
Martin Vasilev
Telerik team
Share this question
or