One way to do this is to set up triggers in your code. The following method applies a trigger to a DataGridColumn. This trigger uses your IsNumericConverter to determine if it needs to be right aligned:
public static void AddTriggerToColumnStyle(DataGridColumn column) { var boundColumn = column as DataGridBoundColumn; if (boundColumn != null && boundColumn.Binding is Binding) { string bindingPropertyPath = (boundColumn.Binding as Binding).Path.Path; column.CellStyle = new Style() { BasedOn = column.CellStyle, TargetType = typeof(DataGridCell), Triggers = { new DataTrigger { Binding = new Binding(bindingPropertyPath) { Converter = new IsNumericConverter() }, Value = true, Setters = { new Setter { Property = TextBlock.TextAlignmentProperty, Value = TextAlignment.Right } } } } }; } }
This method should be safe to call after InitializeComponent() in the code constructor.
This approach will work if the column has a mixture of numeric and non-numeric data. If the columns contain only data of one type, then this approach will still work, but the created triggers will never shoot or stay for long.
Of course, the above method does not have to be repeated in code for each control that uses DataGrids. You can transfer it to the static class of the utility, and all your classes with code code will call this method. You can even add a static utility method that goes through the columns in the DataGrid that you pass in and calls the above method for each column.
UPDATE I modified the above method to allow it to determine the path of the binding property. This facilitates use. I also made the method public and static so that it clears it, and it can be ported to a static class.
I thought of a different approach that would go through all the columns in the DataGrid, check for bindings, infer the type of the associated property, and apply right alignment to the column. This will avoid creating triggers that never fire or never run all the time, and are probably suitable for the case when each column contains the same type of data only slightly better. However, this approach will still be related to the code, it will need to pass the type to which each line is bound, and will become more complicated if the binding property paths include more than one property name.
I am afraid that I do not see a solution to this problem that uses only Style and avoids code.