I recently needed to solve a weird requirement by creating a custom calculator for a XamDataGrid SummaryDefinition. It was not as difficult as I had thought it would be.
The Infragistics example for creating a calculator is very good. You can find it here.
Creating a Custom Summary Calculator - Infragistics WPF™ Help
This post demonstrates how to create a custom calculator. We will create a calculator that displays a sum rounded to the nearest 1000. Start by creating a new WPF C# project called Round2Thousand. I'm using Visual Studio 2022 with .Net Framework but this will work with Core too.
We will start by creating a XamDataGrid and a standard Sum SummaryDefinition.
Add references to Infragistics.WPF4 and Infragistics.WPF4.DataPresenter.
Change MainWindow.xaml to look like this.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Round2Thousand"
xmlns:igDP="http://infragistics.com/DataPresenter"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<igDP:XamDataGrid BindToSampleData="True">
<igDP:XamDataGrid.FieldSettings>
<igDP:FieldSettings AllowEdit="False"/>
</igDP:XamDataGrid.FieldSettings>
<igDP:XamDataGrid.Resources>
<Style TargetType="igDP:SummaryResultPresenter">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</igDP:XamDataGrid.Resources>
<igDP:XamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:FieldLayout.Fields>
<igDP:TextField Label="Name" Name="name"/>
<igDP:TextField Label="Department" Name="department"/>
<igDP:NumericField Label="Salary" Name="salary"/>
<igDP:TextField Label="EMail" Name="email"/>
</igDP:FieldLayout.Fields>
<igDP:FieldLayout.SummaryDefinitions>
<igDP:SummaryDefinition SourceFieldName="salary" Calculator="Sum" StringFormat="{}{0:###,###,##0.00}"/>
</igDP:FieldLayout.SummaryDefinitions>
</igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>
</Grid>
</Window>
internal class Round2ThousandCalculator : SummaryCalculator
{
public override string Description => throw new NotImplementedException();
throw new NotImplementedException();
throw new NotImplementedException();
throw new NotImplementedException();
throw new NotImplementedException();
}
}
public override string Description => "Rounds to nearest thousand";
public override string Name => this.GetType().Name;
The next task is to write the computation. Add a private decimal called Total. This is where we will hold the running total. We initialize this to zero in BeginCalculation. The Aggregate method is called for each row in the table so we make sure the value is a valid decimal and add it to our Total. The EndCalculation method is called at the end to get the final value to be displayed in the summary.
Decimal temp;
}
Total = 0;
}
return Math.Round(Total / 1000).ToString() + " thousand";
We also need to tell Infragistics which data types our calculator supports.
return Utilities.IsNumericType(dataType);
There are two more steps required to consume our calculator.
- Register it
- Reference it
namespace Round2Thousand
public partial class MainWindow : Window
{
public MainWindow()
SummaryCalculator.Register(new Round2ThousandCalculator());
}
}
}
<igDP:SummaryDefinition SourceFieldName="salary" Calculator="Round2ThousandCalculator"/>
The result looks like this
I have to give Infragistics credit for designing this class so well. But I would like to reference it as a StaticResource and avoid the Register code.
internal class HighSalaryCalculator : SummaryCalculator
{
public override string Description => "Calculates the number of employees with Salary >= $100,000";
Decimal temp = 0;
if (temp >= 100000) Count += 1;
}
Count = 0;
}
return Utilities.IsNumericType(dataType);
return $"{Count} @ > $100,000";
}
}
SummaryCalculator.Register(new HighSalaryCalculator());
using Infragistics.Windows.DataPresenter;
internal class SummaryBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
SummaryResultEntry entry = (SummaryResultEntry)value;
return new SolidColorBrush(Colors.Green);
return value;
}
}
<Style TargetType="igDP:SummaryResultPresenter">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="{Binding Converter={StaticResource SummaryBackgroundConverter}}"/>
</Style>
</igDP:XamDataGrid.Resources>
<igDP:FieldLayout.SummaryDefinitions>
<igDP:SummaryDefinition SourceFieldName="salary" Calculator="HighSalaryCalculator" StringFormat="{}{0}"/>
<igDP:SummaryDefinition SourceFieldName="salary" Calculator="MediumSalaryCalculator" StringFormat="{}{0}"/>
<igDP:SummaryDefinition SourceFieldName="salary" Calculator="LowSalaryCalculator" StringFormat="{}{0}"/>
</igDP:FieldLayout.SummaryDefinitions>
No comments:
Post a Comment