简体   繁体   English

如何在WPF中对聚合函数(如sum)进行数据绑定?

[英]How to data-bind an aggregate function (like sum) in WPF?

Imagine I have the following class that implements INotifyPropertyChanged . 想象一下,我有以下实现INotifyPropertyChanged类。 (For brevity, I'm not showing the code that raises the PropertyChanged events, but imagine that each property does.) (为简便起见,我没有显示引发PropertyChanged事件的代码,但可以想象每个属性都可以。)

public class Employee : INotifyPropertyChanged
{
    public string Title { get; set; }
    public string Department { get; set; }
    public double Salary { get; set; }
}

Now, let's say I have four employees: 现在,假设我有四名员工:

     Title         Department    Salary
     -----------------------------------
(1)  Professor     Math           90,000
(2)  Professor     CompSci       120,000
(3)  Instructor    Math           50,000
(4)  Instructor    CompSci        60,000

I'd like to create a table using WPF like the following: 我想使用WPF创建一个表,如下所示:

Title         Math      CompSci    Total
------------------------------------------
Professor     90,000    120,000    210,000
Instructor    50,000     60,000    110,000

It re-arranges the employees by title, showing their salaries for each department in separate columns. 它按标题重新排列员工,并在单独的列中显示每个部门的薪水。 The last column shows the total salary per title. 最后一列显示每个职位的总薪水。

Furthermore, I'd like the user to be able to interact with the table, such as being able to add or remove an employee, or change anyone's salary (and therefore automatically update the total). 此外,我希望用户能够与表进行交互,例如能够添加或删除员工,或更改任何人的薪水(并因此自动更新总数)。

I've been able to do this by re-creating the entire table anytime a change happens. 只要发生更改,我就可以通过重新创建整个表来做到这一点。 But I'd like to be able to do this more efficiently (for example, only update a total when a salary is changed). 但是我希望能够更有效地执行此操作(例如,仅在更改工资后更新总计)。

I've tried to do this, but the code becomes messy really quickly. 我已经尝试过这样做,但是代码很快就变得混乱了。 My view model needs to listen to collection changes in Employees, and whenever one is added, it must listen to its Salary in order to update the Total. 我的视图模型需要侦听Employees中的集合更改,并且每添加一个视图模型,它都必须侦听其薪水以更新总计。 It's hard to follow what's going on, and I imagine it will be a maintenance nightmare later on. 很难跟踪正在发生的事情,并且我认为稍后将是维护的噩梦。

I wish there was a way to bind the total and have it automatically keep track of the necessary changes. 我希望有一种方法可以绑定总数并自动跟踪必要的更改。 Here's some made-up code to show what I mean: 这是一些虚构的代码,以显示我的意思:

<TextBlock Text="{Binding Employees, Aggregate=Sum, Property=Salary}" />

I know this doesn't exist, but is there some easy way to implement what I'm trying to do that's understandable and maintainable? 我知道这是不存在的,但是有什么简单的方法可以实现我可以理解和维护的方法? It doesn't have to be in XAML. 它不必在XAML中。 I'm fine with a programmatic solution as long as it's clear what's going on. 只要知道发生了什么,我就可以使用程序化解决方案。

I'm guessing somewhere you have a master class that has a list of employees like: 我猜你在某个地方有一个大师班,里面有一个像这样的雇员列表:

public ObservableCollection<Employee> Employees { get; private set; }

that you are adding your data to. 您要添加数据的位置。

Now you can create a new output class from it like this: 现在,您可以像这样从中创建一个新的输出类:

public class Summary : ViewModelBase
{
    private string _Title;
    public string Title
    {
        get { return _Title; }
        set { Set(ref _Title, value); }
    }

    private decimal _MathSalary;
    public decimal MathSalary
    {
        get { return _MathSalary; }
        set { Set(ref _MathSalary, value); }
    }

    private decimal _CompSciSalary;
    public decimal CompSciSalary
    {
        get { return _CompSciSalary; }
        set { Set(ref _CompSciSalary, value); }
    }

    private decimal _Total;
    public decimal Total
    {
        get { return _Total; }
        set { Set(ref _Total, value); }
    }
}

and then you can create a total class property that is a get only using this linq query: 然后您可以使用以下linq查询创建一个只能获得的总类属性:

public List<Summary> EmpSum
    {
        get
        {
            return this.Employees.GroupBy(x => x.Title).Select(y => new Summary { Title = y.First().Title, MathSalary = y.Where(s => s.Department == "Math").Sum(s => s.Salary), CompSciSalary = y.Where(s => s.Department == "CompSci").Sum(s => s.Salary), Total = y.Sum(s => s.Salary) }).ToList();
        }
    }

I'm using MVVMLight (ViewModelBase) but you can do your own notification code. 我正在使用MVVMLight(ViewModelBase),但是您可以执行自己的通知代码。 Just need to raisepropertychanged("EmpSum") when you add/remove.change the main list. 添加/删除。更改主列表时,只需要提高propertychanged(“ EmpSum”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM