c# – How to update the value of one cell based on another in Grid View WPF

Question:

I have the following Grid, I would like to know how I can make it so that when I leave the Gain or Spend field it updates the Total?

If there is another way to do it, I'm happy to know.

Total = (Gain – Spend)

    private void txtGanho_LostFocus(object sender, RoutedEventArgs e)
    {
        TextBox txtGanho = (TextBox)sender;
        //Aqui eu tenho o valor do Ganho, como posso encontrar na Grid os TextBox com Gasto e Total
    }

    private void txtGasto_LostFocus(object sender, RoutedEventArgs e)
    {
        TextBox txtGasto = (TextBox)sender;
        //Aqui tenho o valor do Gasto, como posso encontrar na Grid os TextBox com Ganho e Total            
    }     

.xaml file

   <DataGrid x:Name="dgControleFinanceiro" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True" />
            <DataGridTextColumn Header="Data" Binding="{Binding Data}" IsReadOnly="True"/>

            <DataGridTemplateColumn Header="Ganho do dia"  IsReadOnly="False">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Name="txtGanho" Text="{Binding Ganho}" LostFocus="txtGanho_LostFocus"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Gasto do dia"  IsReadOnly="False">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Name="txtGasto" Text="{Binding Gasto}" LostFocus="txtGasto_LostFocus"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Total do dia" IsReadOnly="true">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Name="txtTotal" Text="{Binding Total}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

        </DataGrid.Columns>
    </DataGrid>

Answer:

The best way to do this is through a ViewModel . This ViewModel must implement the INotifyPropertyChanged interface. The UpdateSourceTrigger of the Binding of ValorGanho and ValorGasto properties must be LostFocus , when it loses focus, the set will be executed. So whenever you happen one set in ValorPago or ValorGanho , the View will be notified of the change in Total , reflecting on the grid.

public class ControleFinanceiroViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged = delegate { };

   protected void NotificarMudancaPropriedade([CallerMemberName] string nomePropriedade = null)
   {
     if (nomePropriedade != null)
     {
        PropertyChanged(this, new PropertyChangedEventArgs(nomePropriedade));
     }
   }

   private decimal valorGasto;
   public decimal ValorGasto
   {
     get { return this.valorGasto; }
     set
     {
       this.valorGasto = value;
       this.NotificarMudancaPropriedade();
       this.NotificarMudancaPropridade("Total");
     }
   }

   private decimal valorGanho;
   public decimal ValorGanho
   {
     get { return this.valorGanho; }
     set
     {
       this.valorGanho= value;
       this.NotificarMudancaPropriedade();
       this.NotificarMudancaPropridade("Total");
     }
   }

   public decimal Total 
   {
     get { return this.ValorGanho - this.ValorGasto; }
   }
}

Binding will look like this, and you remove the LostFocus event

<DataTemplate>
    <TextBox Name="txtGanho" Text="{Binding Ganho, Mode = TwoWay, UpdateSourceTrigger = LostFocus}" />
</DataTemplate>

It is not a good practice in WPF to work with events, as it can work with MVVM. And retrieving objects from another grid cell in WPF can be quite cumbersome. So I leave this approach.

https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx

Scroll to Top