Resolved How to get the sum value from the selected rows of a datagrid(specific column) following mvvm ?

TB007

Member
Joined
Aug 13, 2022
Messages
24
Programming Experience
Beginner
I have a Employees model with properties
C#:
        private int _id;
        public int Id
        {
            get
            {
                return _id;
            }
            set
            {
                SetValue(ref _id, value);
            }
        }

        private string _empname;
        public string EmpName
        {
            get
            {
                return _empname;
            }
            set
            {
                SetValue(ref _empname, value);
            }
        }

        private string _empsalary;
        public string EmpSalary
        {
            get
            {
                return _empsalary;
            }
            set
            {
                SetValue(ref _empsalary, value);
            }
        }

        //...other properties like age, address etc.

        //this property is for datagrid selected rows
        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                SetValue(ref_isSelected, value);
            }
        }

In my XAML I have datagrid set up with an ICollectionView FilteredEmps as its itemsource and also

C#:
                                        <DataGrid.RowStyle>
                                            <Style TargetType="DataGridRow">
                                                <Setter Property="IsSelected" Value="{Binding Path = IsSelected}"/>
                                            </Style>
                                        </DataGrid.RowStyle>
In my viewmodel in a method I want to get the sum of EmpSalary of the selected items of the datagrid. How can I do that following MVVM pattern?
I was thinking something like below but it doesn't work.

C#:
        public static decimal SumSalary()
        {
            return FilteredEmps.Cast<Employees>().Select(i=>i.IsSelected).Sum(j => Convert.ToDecimal(j.EmpSalary.ToString()));
        }
 
What doesn't work? Does it not compile? Does it crash? If it doesn't crash, have you set break points to ensure your code is called and inspect values? What did you see while debugging?
 
Well, the intellisense doesn't show me the option of EmpSalary inside the ToDecimal portion

1673183462313.png


So, I think I need to do this using a different approach but not sure what ?
 
Select(i=>i.IsSelected) is selecting booleans, j in following Sum expression is a bool value. Instead of Select try a Where expression.
 
Do not use random letters for argument names in lambdas; use something more relevant to the type or the instance

C#:
FilteredEmps.Select(e=>e.IsSelected).Sum(b => Convert.ToDecimal(b.EmpSalary.ToString()))

FilteredEmps ought to be a typed collection such as List<Employee>, then you wouldn't need a cast

e is so called because the argument provided to Select is an employee

b is so called because the input to the Sum IIS the bool output by the select

You can point to any variable or argument at any time to get VS to tell you what it thinks
 
Do not use random letters for argument names in lambdas; use something more relevant to the type or the instance

C#:
FilteredEmps.Select(e=>e.IsSelected).Sum(b => Convert.ToDecimal(b.EmpSalary.ToString()))

FilteredEmps ought to be a typed collection such as List<Employee>, then you wouldn't need a cast

e is so called because the argument provided to Select is an employee

b is so called because the input to the Sum IIS the bool output by the select

You can point to any variable or argument at any time to get VS to tell you what it thinks
FilteredEmps is an ICollectionView.

So your approach shows error
'System.ComponentModel.ICollectionView' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.ComponentModel.ICollectionView' could be found (are you missing a using directive or an assembly reference?) (CS1061)
 
FilteredEmps ought to be a typed collection

The operative word is "ought", meaning if you are striving to make sensible and repeated use of a class level collection then it is wise to make it easier to work with in some way, such as making it a List<Employee>

LINQ is hard enough to grok without needlessly throwing obstacles into your own path; most of the response I gave was with that aim in mind

C#:
 Employees.GroupBy(e => e.Department, (d, g) => new { Dept = d, AvgSal = g.Avg(e => e.Salary) }).OrderBy(at => at.AvgSal);

LINQ grouping can get pretty convoluted. Here the aim is to keep is clear and straight; Employees is a list of Employee. The "e" is some employee from the list. The grouping groups employees by department. "d" is the key to the group, and is the department name (a string). The output of the grouping is an anonymous type of the dept name (from the grouping key) and a calculation on the group of employees, "g". "g" is like a list of employees so when we run a sub expression on it to calc the average salary for an employee, we can use "e" again to refer to any particular employee in g. The "e" here is not necessarily the same as the earlier "e", but they're both employees. By the time we are ordering we are ordering a bunch of anonymous types, so I've called it "at"
 
Last edited:
Back
Top Bottom