Home > database >  Datagridview Dynamic cell calculation
Datagridview Dynamic cell calculation

Time:09-14

I have two columns in Datagridview, one for the price excluding Vat and another one for price including Vat, I want it to be dynamic, if I alter the price excluding vat it updates the column including Vat, and if I Update the including Vat column it updates the excluding VAT column vice-versa.

I would appreciate if anyone can help me with the right code for it in C#.

Here´s the code I´m using the calculation to one direction I need the code for the inverse.

  private void dgv_Filho_CellEndEdit_1(object sender, DataGridViewCellEventArgs e)
        {
            bool Check = Convert.ToBoolean(dgv_Filho.CurrentRow.Cells["Check_Filho"].Value);
            string Medida_1 = Convert.ToString(dgv_Filho.CurrentRow.Cells["Medida_1"].Value);
            string Medida_2 = Convert.ToString(dgv_Filho.CurrentRow.Cells["Medida_2"].Value);

            var Iva = Convert.ToDecimal(cb_Iva.Text);

            if (Check)
            {
                if (!string.IsNullOrWhiteSpace(tb_CodigoArtigo.Text) || !string.IsNullOrWhiteSpace(tb_Descricao.Text))
                {
                    dgv_Filho.CurrentRow.Cells["ArtigoPai"].Value = tb_CodigoArtigo.Text;
                    dgv_Filho.CurrentRow.Cells["Descricao_Pai"].Value = tb_Descricao.Text   " "   Medida_1   Medida_2;
                    dgv_Filho.CurrentRow.Cells["CodigoArtigoFilho"].Value = tb_CodigoArtigo.Text   Medida_1   Medida_2;
                    //dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value = tb_PVP1.Text;

                    decimal PrecoFilho = Convert.ToDecimal(dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value);
                    if (PrecoFilho > 0)
                    {
                        decimal PrecoFilhoComIva = PrecoFilho * Iva / 100   PrecoFilho;
                        dgv_Filho.CurrentRow.Cells["PrecoFilhoComIva"].Value = PrecoFilhoComIva;
                    }
                }
                else
                {
                    dgv_Filho.CurrentRow.Cells["ArtigoPai"].Value = string.Empty;
                    dgv_Filho.CurrentRow.Cells["Descricao_Pai"].Value = string.Empty;
                }
            }
        }

CodePudding user response:

I can't tell how you are pulling your information in, but you will have to set up an event handler to monitor your variable, and use the event to refresh your datagridview

CodePudding user response:

Rather than interact with the DataGridView directly (which can be complex) you could instead make a class that implements INotifyPropertyChanged and keeps all of its internal calculations up-to-date at all times (which is easier). Here is a simplified version of such a class that responds to changes of Descricao, Medida and PrecoFilhoSemIva.


Simplified class that represents a row of data

class Articulo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    string _descricao = string.Empty;
    public string Descricao
    {
        get => _descricao;
        set
        {
            if (!Equals(_descricao, value))
            {
                _descricao = value;
                OnPropertyChanged();
            }
        }
    }
    public string Descricao_Pai => $"{Descricao} {Medida_1}@{_precoFilhoSemIva.ToString("F2")}";
    public decimal PrecoFilhoComIva => _precoFilhoSemIva * (1.0m   MainForm.Iva);

    decimal _medida = 0;
    public decimal Medida
    {
        get => _medida;
        set
        {
            if (!Equals(_medida, value))
            {
                _medida = value;
                OnPropertyChanged();
            }
        }
    }

    decimal _precoFilhoSemIva = 0;
    public decimal PrecoFilhoSemIva
    {
        get => _precoFilhoSemIva;
        set
        {
            if (!Equals(_precoFilhoSemIva, value))
            {
                _precoFilhoSemIva = value;
                OnPropertyChanged();
            }
        }
    }
    string _codigoArtigo = System.Guid.NewGuid().ToString().Substring(0, 10).ToUpper();
    public string CodigoArtigo
    {
        get => _codigoArtigo;
        set
        {
            if (!Equals(_codigoArtigo, value))
            {
                _codigoArtigo = value;
                OnPropertyChanged();
            }
        }
    }
}

Instances of this class are placed in a BindingList which is assigned to the DataSource property of dgv_Filho and caused the DGV to update whenever the Refresh method is called.

Change Iva

Change Descricao

Change Preco


Initializations

The only interaction that should be necessary with the DGV is to initialize the columns and bindings properly in the MainForm override for the Load event. This is also where we bind the combo box to a static value for Iva that can be used by the calculation for the row items.

protected override void onl oad(EventArgs e)
{
    base.OnLoad(e);
    initDataGridView();
    initComboBox();
}
private void initDataGridView()
{
    dgv_Filho.DataSource = DataSource;
    DataSource.ListChanged  = (sender, e) =>
    {
        if (e.ListChangedType == ListChangedType.ItemChanged)
        {
            dgv_Filho.Refresh();
        }
    };
    // Add one or more items to autogenerate the columns.
    Random randomPriceGen = new Random(1);
    for (int i = 1; i <= 3; i  )
    {
        var preco = i == 1 ? 1.0m : (decimal)randomPriceGen.NextDouble() * 100;
        DataSource.Add(new Articulo
        {
            Descricao = $"Articulo {(char)('A'   (i - 1))}",
            Medida = i,
            PrecoFilhoSemIva = preco,
        });
    }
    // Do a little column formatting
    foreach (DataGridViewColumn column in dgv_Filho.Columns)
    {
        switch (column.Name)
        {
            case nameof(Articulo.Descricao):
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                column.MinimumWidth = 120;
                break;
            case nameof(Articulo.Medida):
            case nameof(Articulo.PrecoFilhoSemIva):
            case nameof(Articulo.PrecoFilhoComIva):
                column.DefaultCellStyle.Format = "F2";
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                break;
            default:
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                break;
        }
    }
}
private void initComboBox()
{
    cb_Iva.SelectedIndex = 0;
    cb_Iva.SelectedIndexChanged  = onIvaSelected;
    cb_Iva.KeyDown  = (sender, e) =>
    {
        if( e.KeyData == Keys.Enter)
        {
            e.Handled = e.SuppressKeyPress = true;
        }
        onIvaSelected(sender, e);
    };
    onIvaSelected(cb_Iva, EventArgs.Empty);

    void onIvaSelected(object sender, EventArgs e)
    {
        if (decimal.TryParse(cb_Iva.Text.Replace("%", string.Empty), out decimal iva))
        {
            Iva = iva / 100m;
            dgv_Filho.Refresh();
            cb_Iva.BackColor = SystemColors.Window;
        }
        else cb_Iva.BackColor = Color.LightSalmon;
    }
}
  • Related