wpffilteringobservablecollectionicollectionview

sum of filtered ICollectionView


suppose this base class

public class Contrat_Paye_Item 
    {
        public int     CPI_TYPE { get; set; }
        public string  CPI_TEXT { get; set; }
        public decimal CPI_AMOUNT { get; set; }
    }

in my view Model i have made a list from that class like this :

private ObservableCollection<Contrat_Paye_Item> listapayer;
public ObservableCollection<Contrat_Paye_Item> ListaPayer
{
    get
    {
        return listapayer;
    }
    set
    {
        listapayer = value;
        OnPropertyChanged("ListaPayer");
    }
}

and in the VM constructor, just some testdata :

 listapayer.Add(new Contrat_Paye_Item()
                    {
                        CPI_TYPE = 0,
                        CPI_TEXT = "Loyer",
                        CPI_AMOUNT = 100
                    });


listapayer.Add(new Contrat_Paye_Item()
                    {
                        CPI_TYPE = 1,
                        CPI_TEXT = "charge 1",
                        CPI_AMOUNT = 200
                    });

listapayer.Add(new Contrat_Paye_Item()
                    {
                        CPI_TYPE = 1,
                        CPI_TEXT = "Charges 2",
                        CPI_AMOUNT = 300
                    });

so the full list contain 3 item, the total Amount is 600 .

in my viewmodel i have added a sublist with only items that their CPI_TYPE = 1 and bound it to a listbox without problem like this :

   public ICollectionView ListCharges
        {
            get
            {


                var sub= new CollectionViewSource { Source = listapayer }.View;
                sub.Filter = p => (p as Contrat_Paye_Item).CPI_TYPE == 1;
                return sub;
            }
        }

now what i want to display is a list of my items , with a row that contain a sum of amounts items of the sublist . a bind it to a second listbox

something like :

loyer 100

charges 500

any idea, tip is welcome . thanks


Solution

  • How about adding something like this before returning the sub:

            var d1 = (from a in sub.SourceCollection.OfType<Contrat_Paye_Item>() where a.CPI_TEXT == "Loyer" select a.CPI_AMOUNT).Sum();
            var d2 = (from a in sub.SourceCollection.OfType<Contrat_Paye_Item>() where a.CPI_TEXT.ToLower().StartsWith("charge") select a.CPI_AMOUNT).Sum();
    
            sub.AddNewItem(new Contrat_Paye_Item() { CPI_TEXT="Sum Loyer", CPI_AMOUNT = d1} );
            sub.CommitNew();
            sub.AddNewItem(new Contrat_Paye_Item() { CPI_TEXT = "Sum Charges", CPI_AMOUNT = d2 });
            sub.CommitNew();
    

    //Edit

    Note this as a more flexible possibility:

    Do not use _CollectionViewSource _. Instead use the following as the ItemsSource of the ListBox:

         public ObservableCollection<Contrat_Paye_Item> ListCharges
        {
            get
            { 
                return new ObservableCollection<Contrat_Paye_Item>((from a in listapayer where a.CPI_TYPE == 1 select a));
            }
        }