New to Telerik UI for WinForms? Download free 30-day trial

Create an editable summary row.

Environment

Product Version Product Author
2022.1.222 RadGridView for WinForms Dinko Krastev

Description

Some scenarios will require to have an editable summary row. This article shows how to achieve this functionality, so when the user clicks on the summary cell, the editor will appear. Editing the summary cell value will affect the values of the cells in this column. For the purpose of this tutorial, we will populate our RadGridVew with custom data and set the second column to be GridViewDecimalColumn. The value in the summary cell will represent the sum of all cells inside this column. Modifying the summary cell will proportionally change the values inside each cell.

EditableSummaryRow

Solution

  1. First we need to populate our RadGridVew with some dummy data.

public class Country :ViewModelBase
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value;this.OnPropertyChanged("Name"); }
    }

    private double cost;
    public double Cost
    {
        get { return cost; }
        set { cost = value; this.OnPropertyChanged("Cost"); }
    }
}

public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
    public RadForm1()
    {
        InitializeComponent();
        BindingList<Country> countries = new BindingList<Country>();
        countries.Add(new Country() { Name = "Bulgaria", Cost = 200 });
        countries.Add(new Country() { Name = "United States", Cost = 200 });
        countries.Add(new Country() { Name = "United Kingdom", Cost = 400 });
        countries.Add(new Country() { Name = "Germany", Cost = 200 });

        this.radGridView1.AutoGenerateColumns = false;
        this.radGridView1.Columns.Add(new GridViewTextBoxColumn("Name"));
        this.radGridView1.Columns.Add(new CustomColumn("Cost"));
        this.radGridView1.DataSource = countries;

        GridViewSummaryItem summaryItem = new GridViewSummaryItem();
        summaryItem.Name = "Cost";
        summaryItem.Aggregate = GridAggregateFunction.Sum;

        GridViewSummaryRowItem summaryRowItem = new GridViewSummaryRowItem();
        summaryRowItem.Add(summaryItem);

        this.radGridView1.SummaryRowsTop.Add(summaryRowItem);
    }
}

  1. Now to implement editable summary cell, we need to create custom column(GridViewDecimalColumn) and replace the default summary cell with a custom one.

public class CustomColumn : GridViewDecimalColumn
{
    public CustomColumn(string fieldName) : base(fieldName) { }

    public override Type GetCellType(GridViewRowInfo row)
    {
        if (row is GridViewSummaryRowInfo && this.FieldName == "Cost")
        {
            return typeof(CustomSummaryCell);
        }
        return base.GetCellType(row);
    }
}         
  1. The final step will be our custom summary cell. Your class should derive from the GridDataCellElement so that you can get advantage of the default editing mechanism and editor. In the following code snippet, you can observe that we have subscribe to the ValueChanged of the editor. In the event handler, when the summary cell is edited, the values inside the cells will proportionally change.

public class CustomSummaryCell : GridDataCellElement
{
    private double initialValue = -1;       
    public CustomSummaryCell(GridViewColumn column, GridRowElement row) : base(column, row)
    {

    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        this.GridControl.CurrentRow = this.RowInfo;
        this.GridControl.CurrentColumn = this.ColumnInfo;
        this.IsCurrent = true;
        this.GridViewElement.BeginEdit();
        if (this.Editor != null)
        {
            var spinEditor = this.Editor as GridSpinEditor;
            spinEditor.Step = 200;
            spinEditor.MinValue = 200;
            spinEditor.ValueChanged += SpinEditor_ValueChanged;
        }
    }
    public override bool IsCompatible(GridViewColumn data, object context)
    {
        if (data is CustomColumn && context is GridViewSummaryRowInfo)
        {
            return true;
        }
        return base.IsCompatible(data, context);
    }
    private void SpinEditor_ValueChanged(object sender, EventArgs e)
    {
        this.Editor.ValueChanged -= SpinEditor_ValueChanged;
        var gridSpinEditor = this.Editor as GridSpinEditor;

        if (gridSpinEditor == null)
        {
            return;
        }

        var newTextBoxValue = double.Parse(gridSpinEditor.Value.ToString());

        if (newTextBoxValue < 100)
        {
            gridSpinEditor.Value = 100;
            return;
        }

        if (Double.TryParse(this.Value + "", out initialValue))
        {

            var increase = newTextBoxValue - initialValue;
            bool isIncreased = true;
            if (increase < 0)
            {
                increase = increase * -1;
                isIncreased = false;
            }

            double percentComplete = Math.Round((double)(100 * increase) / initialValue) / 100;

            var sourceCollection = this.RowInfo.ViewTemplate.DataSource as BindingList<Country>;
            double currentSum = 0;
            this.RowInfo.ViewTemplate.BeginUpdate();
            foreach (var item in sourceCollection)
            {
                if (isIncreased)
                {
                    item.Cost += Math.Round(item.Cost * percentComplete, 1);
                }
                else
                {
                    item.Cost -= Math.Round(item.Cost * percentComplete, 1);

                }

                if (item.Cost <= 0)
                {
                    item.Cost = 1;
                }

                currentSum += item.Cost;
            }
            if (currentSum != newTextBoxValue)
            {
                sourceCollection.Last().Cost += newTextBoxValue - currentSum;
            }
            this.Editor.ValueChanged += SpinEditor_ValueChanged;

            this.RowInfo.ViewTemplate.EndUpdate();
        }

    }
    public override void RemoveEditor(IInputEditor editor)
    {
        this.Editor.ValueChanged -= SpinEditor_ValueChanged;
        base.RemoveEditor(editor);
    }
}

In this article