Example E4883
Visible to All Users

WinForms Data Grid - Cancel current row modifications at the GridView level

Windows Forms binding allows you to discard changes made in a data item (row/record). This feature is available for data objects that implement IEditableObject (CurrencyManager.CancelCurrentEdit).

Entity Framework 4 comes with POCO support that allows developers to define entities (base classes are not required). By not inheriting from the underlying entities of the framework, developers lost the built-in implementations of IEditableObject and INotifyPropertyChanged interfaces (for example, the capability to undo changes to a grid control if data validation fails).

This example demonstrates how to address this issue at the GridView level. The example creates a custom Grid View. The custom GridView uses a new data controller (inherited from the CurrencyDataController class) and overrides the following methods: BeginCurrentRowEdit, EndCurrentRowEdit, and CancelCurrentRowEdit.

Files to Review

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

DxSample/Form1.cs(vb)
C#
using DevExpress.Utils; using DevExpress.XtraGrid.Views.Base; 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; namespace DxSample { public partial class Form1 :Form { public Form1() { InitializeComponent(); } private void OnValidateRow(object sender, ValidateRowEventArgs e) { Person p = (Person)e.Row; e.Valid = string.IsNullOrEmpty(p.Name) || p.Name.Contains("A"); } } }
DxSample/Grid/CancellingChangesDataController.cs(vb)
C#
using DevExpress.Data; using System; using System.Collections.Generic; using System.ComponentModel; namespace DxSample.Grid { public class CancellingChangesDataController :CurrencyDataController { class ColumnValuePair { public DataColumnInfo Column { get; set; } public object Value { get; set; } public void Free() { Column = null; Value = null; } } List<ColumnValuePair> originalValues = new List<ColumnValuePair>(); public bool CanCancelChanges { get; set; } bool ShouldCancelChanges { get { return CanCancelChanges && CurrentControllerRow != NewItemRow && !(CurrentControllerRowObject is IEditableObject); } } public override void BeginCurrentRowEdit() { base.BeginCurrentRowEdit(); if (ShouldCancelChanges && originalValues.Count == 0) foreach (DataColumnInfo col in Columns) originalValues.Add(new ColumnValuePair() { Column = col, Value = GetCurrentRowValue(col) }); } public override bool EndCurrentRowEdit(bool force) { bool result = base.EndCurrentRowEdit(force); if (result) { foreach (ColumnValuePair val in originalValues) val.Free(); originalValues.Clear(); } return result; } public override void CancelCurrentRowEdit() { base.CancelCurrentRowEdit(); foreach (ColumnValuePair val in originalValues) { SetCurrentRowValue(val.Column, val.Value); val.Free(); } originalValues.Clear(); } public override void Dispose() { foreach (ColumnValuePair val in originalValues) val.Free(); originalValues.Clear(); base.Dispose(); } } }
DxSample/Grid/GridControlEx.cs(vb)
C#
using DevExpress.XtraGrid; using DevExpress.XtraGrid.Registrator; namespace DxSample.Grid { public class GridControlEx :GridControl { protected override void RegisterAvailableViewsCore(InfoCollection collection) { base.RegisterAvailableViewsCore(collection); collection.Add(new GridViewExInfoRegistrator()); } } }
DxSample/Grid/GridViewEx.cs(vb)
C#
using DevExpress.Data; using DevExpress.Utils.Controls; using DevExpress.Utils.Serializing; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Views.Base; using DevExpress.XtraGrid.Views.Grid; using System; using System.ComponentModel; namespace DxSample.Grid { public class GridViewEx :GridView { public GridViewEx() : base() { } public GridViewEx(GridControl ownerGrid) : base(ownerGrid) { } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), XtraSerializableProperty(XtraSerializationVisibility.Content)] public new GridViewExOptionsBehavior OptionsBehavior { get { return (GridViewExOptionsBehavior)base.OptionsBehavior; } } protected override ColumnViewOptionsBehavior CreateOptionsBehavior() { return new GridViewExOptionsBehavior(this); } protected override BaseGridController CreateDataController() { if (requireDataControllerType == DataControllerType.Regular) return new CancellingChangesDataController(); return base.CreateDataController(); } protected override string OnCreateLookupDisplayFilter(string text, string displayMember) { throw new NotSupportedException("This view cannot be used in lookup editors"); } protected override void UpdateDataControllerOptions() { base.UpdateDataControllerOptions(); CancellingChangesDataController controller = DataController as CancellingChangesDataController; if (controller != null) controller.CanCancelChanges = OptionsBehavior.CanCancelChanges; } } }
DxSample/Grid/GridViewExInfoRegistrator.cs(vb)
C#
using DevExpress.XtraGrid; using DevExpress.XtraGrid.Registrator; using DevExpress.XtraGrid.Views.Base; namespace DxSample.Grid { public class GridViewExInfoRegistrator :GridInfoRegistrator { public override string ViewName { get { return "GridViewEx"; } } public override BaseView CreateView(GridControl grid) { return new GridViewEx(grid); } } }
DxSample/Grid/GridViewExOptionsBehavior.cs(vb)
C#
using DevExpress.Utils.Controls; using DevExpress.XtraGrid.Views.Base; using DevExpress.XtraGrid.Views.Grid; using System.ComponentModel; namespace DxSample.Grid { public class GridViewExOptionsBehavior :GridOptionsBehavior { public GridViewExOptionsBehavior() : base() { } public GridViewExOptionsBehavior(ColumnView view) : base(view) { } bool fCanCancelChanges; [DefaultValue(false)] public bool CanCancelChanges { get { return fCanCancelChanges; } set { if (fCanCancelChanges == value) return; bool prevValue = CanCancelChanges; fCanCancelChanges = value; OnChanged(new BaseOptionChangedEventArgs("CanCancelChanges", prevValue, CanCancelChanges)); } } public override void Assign(BaseOptions options) { BeginUpdate(); try { base.Assign(options); GridViewExOptionsBehavior opt = options as GridViewExOptionsBehavior; if (opt == null) return; fCanCancelChanges = opt.CanCancelChanges; } finally { EndUpdate(); } } } }
DxSample/Person.cs(vb)
C#
using System.ComponentModel; namespace DxSample { public class Person { public string Name { get; set; } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.