Skip to content

Excel accounting style column for WPF DataGrid

April 27, 2011

For our WPF applications we had a requirement that the WPF DataGrid must be able to show amounts just like the Excel accounting format. In short this means: currency symbol aligned to the left and the amount aligned to the right within a column. Default such column is not available but with some effort it is relative simple to create this kind of a column.

First we create a control which shows an amount like the Excel accounting style.

<Style TargetType="{x:Type local:AccountingCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:AccountingCell}">
                <Grid Margin="2,0,2,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{x:Static local:DataGridHelper.CurrencySymbol}" VerticalAlignment="Center"></TextBlock>
                    <TextBlock Grid.Column="1" Text="{TemplateBinding Amount}" TextAlignment="Right" VerticalAlignment="Center"></TextBlock>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
public class AccountingCell : Control
{
    static AccountingCell()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(AccountingCell), new FrameworkPropertyMetadata(typeof(AccountingCell)));
    }

    public string Amount
    {
        get { return (string)GetValue(AmountProperty); }
        set { SetValue(AmountProperty, value); }
    }

    public static readonly DependencyProperty AmountProperty =
        DependencyProperty.Register("Amount", typeof(string), typeof(AccountingCell), new UIPropertyMetadata(null));        
}

The AccountingCell control derives from Control and has one extra dependency property of type string which is named Amount. The DataGridHelper class (line 10) is just a helper class which reads the currency symbol from the regional settings (Current culture).

The next step is creating a DataGridAccountingColumn class which derives from the DataGridTextColumn. A dependency property is added for setting the number of decimal digits used for formatting the amount. We override the GenerateElement method which is responsible for creating the elements when the cell is not in edit mode.

public class DataGridAccountingColumn : DataGridTextColumn
{
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        AccountingCell accountingCell = new AccountingCell();

        Binding newBinding = new Binding(((Binding)Binding).Path.Path);
        
        string decimalPattern = new String('0', DecimalDigits);
        string accountingFormat = "{0:#,##0." + decimalPattern + "}";
        newBinding.StringFormat = accountingFormat;
        // Ensure the current culture passed into bindings is the OS culture.
        // By default, WPF uses en-US as the culture, regardless of the system settings.
        newBinding.ConverterCulture = System.Threading.Thread.CurrentThread.CurrentCulture;

        accountingCell.SetBinding(AccountingCell.AmountProperty, newBinding);

        return accountingCell;
    }
        
    public int DecimalDigits
    {
        get { return (int)GetValue(DecimalDigitsProperty); }
        set { SetValue(DecimalDigitsProperty, value); }
    }

    public static readonly DependencyProperty DecimalDigitsProperty =
        DependencyProperty.Register("DecimalDigits", typeof(int), typeof(DataGridAccountingColumn), new UIPropertyMetadata(2));        

}

In the GenerateElement method we create an AccountingCell object and create a new binding based on the orginal column binding because we cannot change the orginal binding. On the new binding we set the StringFormat property so the amount is properly formatted.

Now we can use the accounting column as follows:

<DataGrid ItemsSource="{Binding }" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <local:DataGridAccountingColumn Header="Accounting style" Binding="{Binding Amount}"></local:DataGridAccountingColumn>
     </DataGrid.Columns>
</DataGrid>

As you can see the result is a column which shows the amount just like the Excel accounting format.

Source code can be downloaded from here.

About these ads

From → .NET, DataGrid, WPF

2 Comments

Trackbacks & Pingbacks

  1. test blasts are fun

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: