Capture the Checked of a CheckBox inside a Datagrid from the ViewModel

2

I have a requirement in WPF , I made a ViewModel called AsignaFacturasVM for my View, in which I have a Label that is linked to a property float called Accumulated Amount of my ViewModel and I also have a Datagrid whose ItemSource is a property of my ViewModel which is a ObservableCollection called AccountsxChoose which contains a float called Amount (which I edit within the Datagrid with a TextBox ) and a bool called Selected (which I edit within the DataGrid with a CheckBox ).

What I need to do, is that every time the user checks in CheckBox , the property AmountAcumulated is updated, adding all the Amount of the rows of DataGrid who have Selected in true .

I hope you explained.

For this, I have a function within my ViewModel that is responsible for accumulating these amounts depending on whether it is selected in true, but I could not find how and at what time to launch this function, the data in my collection and in my ViewModel are updated correctly depending on what the user changes in View , I just need to make the calculation of the Amount Accumulated ...

Inside my ViewModel cs:

    private ObservableCollection<CuentasxCobrarCL> _cuentasxcobrar;
    public ObservableCollection<CuentasxCobrarCL> CuentasxCobrar
    {
        set
        {
            _cuentasxcobrar = value;
            ActualizaImporteAcumulado();
            OnPropertyChanged("CuentasxCobrar");
            OnPropertyChanged("ImporteAcumulado");
        }
        get { return _cuentasxcobrar; }
    }

        private void ActualizaImporteAcumulado()
    {
        _importeacumulado = 0;
        foreach (var item in _cuentasxcobrar)
        {
            _importeacumulado += item.seleccionada ? item.importepago : 0;
        }
        OnPropertyChanged("ImporteAcumulado");
    }

On my XAML:

<sdk:DataGridTemplateColumn Header="Seleccionar" Width="95" CanUserSort="False"  >
<sdk:DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <CheckBox Name="chkseleccionada"                                                       
                    IsChecked="{Binding seleccionada, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
            NotifyOnValidationError=True,
            ValidatesOnExceptions=True, 
            ValidatesOnNotifyDataErrors=True, 
            ValidatesOnDataErrors=True}"
                    HorizontalAlignment="Center"  />
    </DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <CheckBox IsChecked="{Binding seleccionada, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
            NotifyOnValidationError=True,
            ValidatesOnExceptions=True, 
            ValidatesOnNotifyDataErrors=True, 
            ValidatesOnDataErrors=True}" />                                            
    </DataTemplate>        
</sdk:DataGridTemplateColumn.CellEditingTemplate>

Part of my AccountsxCobrarCL.cs:

    public class CuentasxCobrarCL : INotifyPropertyChanged
{
    public int idcli { get; set; }
    public DateTime fecha { get; set; }
    public DateTime fechadepago { get; set; }
    #region public float importepago
    private float _importepago;
    public float importepago 
    {
        get
        { return _importepago; }
        set
        {
            _importepago = value;
            _saldonuevo = _adeudo - _importepago;
            OnPropertyChanged("saldonuevo");
            OnPropertyChanged("importepago");
        }
    }
    #endregion

    #region public bool seleccionada
    private bool _seleccionada;
    public bool seleccionada
    {
        get
        { return _seleccionada; }
        set
        {
            _seleccionada = value;
            OnPropertyChanged("seleccionada");
        }
    }
    #endregion

    #region PropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

Any suggestions?

    
asked by Cyndy 10.07.2018 в 23:31
source

2 answers

2

You have to make a couple of changes to make it work. The main thing is to know that observable collection does not trigger the on change method when changing some value of the objects it contains, but only when the observablecollection changes itself.

We must have a way of knowing when the daughter class is updated, and notify the parent, who has the observableCollection, that he has to update the value of the check.

The problem? there is no simple way to do this. We must put together an event for each time the daughter class changes, and this is a problem, because we must have an event for each child.

In your case, we're going to do something else.

We need to add a property to your VM that knows which item is selected in the grid, and when another item is selected in the grid, recalculate the total.

Add the following to your grid:

SelectedItem="{Binding ItemSeleccionado, Mode=TwoWay}"

Then, to your vm, add the following:

CuentasxCobrarCL _ItemSeleccionado;
public CuentasxCobrarCL ItemSeleccionado
{
    get
    {
        return _ItemSeleccionado;
    }
    set
    {
        _ItemSeleccionado= value;
        ActualizaImporteAcumulado();
    }
}

With this, every time you change rows, the value of your total should be updated.

    
answered by 11.07.2018 / 01:57
source
0

You can declare the list as an object itself and place the total as a property in the list:

public class CuentasxCobrarCL
{
    //[...]
}
public class CuentasCollection : ObservableCollection<CuentasxCobrarCL>
{
    public float TotalPago()
    {
        float total = 0;
        for (int i = 0; i < this.Count; i++)
        {
            if (this[i].seleccionada)
            {
                total += this[i].importepago;
            }
        }

        return total;
    }
}

Then, in the ViewModel in the propertyChanged event you will update that value automatically because it will be inside the list

private CuentasCollection _cuentasxcobrar = new CuentasCollection();
public CuentasCollection CuentasxCobrar
{
    set
    {
        _cuentasxcobrar = value;
        OnPropertyChanged("CuentasxCobrar");

    }
    get { return _cuentasxcobrar; }
}

I do not pretend to be the answer, but I think it can help you if you know how to apply it.

    
answered by 11.07.2018 в 06:08