Как добавить средневзвешенную сводку в DevExpress XtraGrid?

DevExpress Grid (XtraGrid) позволяет сеткам и их группам выполнять сводные вычисления. Доступны следующие параметры: «Количество», «Макс.», «Мин.», «Среднее», «Сумма», «Нет» и «Пользовательский».

У кого-нибудь есть пример кода, показывающий, как рассчитать средневзвешенный столбец на основе весов, представленных в виде значений в другом столбце?


person Drew Noakes    schedule 20.02.2009    source источник


Ответы (2)


Я закончил тем, что разобрался с этим, и опубликую свое решение здесь, если другие сочтут его полезным.

Если средневзвешенное значение состоит как из значения, так и из веса для каждой строки, то столбец, содержащий значение, должен иметь объект GridColumn веса, назначенный его свойству Tag. Затем этот обработчик событий сделает все остальное:

private static void gridView_CustomSummaryCalculate(object sender, CustomSummaryEventArgs e)
{
    GridColumn weightColumn = ((GridSummaryItem)e.Item).Tag as GridColumn;

    if (weightColumn == null)
        return;

    switch (e.SummaryProcess)
    {
        case CustomSummaryProcess.Start:
        {
            e.TotalValue = new WeightedAverageCalculator();
            break;
        }
        case CustomSummaryProcess.Calculate:
        {
            double size = Convert.ToDouble(e.FieldValue);
            double weight = Convert.ToDouble(((GridView)sender).GetRowCellValue(e.RowHandle, weightColumn));

            ((WeightedAverageCalculator)e.TotalValue).Add(weight, size);
            break;
        }
        case CustomSummaryProcess.Finalize:
        {
            e.TotalValue = ((WeightedAverageCalculator)e.TotalValue).Value;
            break;
        }
    }
}

private sealed class WeightedAverageCalculator
{
    private double _sumOfProducts;
    private double _totalWeight;

    public void Add(double weight, double size)
    {
        _sumOfProducts += weight * size;
        _totalWeight += weight;
    }

    public double Value
    {
        get { return _totalWeight==0 ? 0 : _sumOfProducts / _totalWeight; }
    }
}

Код предполагает, что базовые значения столбца могут быть преобразованы в двойные значения с помощью Convert.ToDouble(object).

person Drew Noakes    schedule 20.02.2009

Если вы предоставите собственное лямбда-выражение внутри суммы, вы сможете сгруппировать их по стандартной сумме. Я думаю, что это должно работать:

var grouped = from item in items
orderby item.Group
group item by item.Group into grp
select new
{
Average= grp.Sum(row => row.Value * row.Weight)
};
person MBirchmeier    schedule 20.02.2009
comment
@MBirchmeier, спасибо за ответ, но это не будет интегрироваться с API элемента управления сеткой. - person Drew Noakes; 20.02.2009
comment
Извините, рано утром я подумал, что LINQ можно использовать в качестве источника данных, не утруждая себя проверкой. Я бы предположил, что вам нужно использовать «пользовательскую» функцию, но я не могу найти никакой документации по ней навскидку. - person MBirchmeier; 20.02.2009