Экспоненциальная запись в TextBlock

1,00
р.
Как в DataGridTextColumn реализовать переход на экспоненциальную запись, когда не хватает места для полного отображения числа.
Желаемый эффект:

Есть идея использовать конвертор, и вызывать его всякий раз при изменении ширины колонки. В конверторе использовать StringFormat. Возникают дополнительные вопросы:
на какое событие нужно подписаться которое бы отслеживало изменение размера колонки? как определять сколько символов влезает в ячейку, чтобы знать сколько символов отобразить после запятой и до E?
P.S. Что-то подобное делает свойство TextTrimming="CharacterEllipsis" у TextBlock. при нехватке места для отображения часть символов заменяется многоточием. Если узнать каким способом TextBlock определяет что ему не хватает места отобразить текст, то может и получиться решить данный вопрос.

Ответ
По идее, для этого можно приспособить UserControl и немного code-behind. Для измерения ширины текста без отображения подойдёт класс FormattedText. Вот простой набросок:
Контрол:

Code-behind:
public partial class DoubleWidthFitControl : UserControl { public DoubleWidthFitControl() { InitializeComponent() SizeChanged += (o, args) => Recalc() }
#region dp double Value public double Value { get { return (double)GetValue(ValueProperty) } set { SetValue(ValueProperty, value) } }
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(double), typeof(DoubleWidthFitControl), new PropertyMetadata(0.0, (o, args) => ((DoubleWidthFitControl)o).Recalc())) #endregion
void Recalc() { var targetWidth = ActualWidth var num = Value
string s // у C# 7 есть локальные функции, вау! bool CheckLength(string format) { s = num.ToString(format) return Measure(s) <= targetWidth }<br> if (CheckLength("F") || CheckLength("G")) { Target.Text = s return }
int i for (i = 0 CheckLength($"E{i}") i++) /**/ if (i == 0) Target.Text = "###" else Target.Text = num.ToString($"E{i - 1}") }
double Measure(string s) { TextBlock tb = Target var formattedText = new FormattedText( s, CultureInfo.CurrentCulture, tb.FlowDirection, new Typeface(tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), tb.FontSize, Brushes.Black) return formattedText.Width } }
Использовать просто:

Результат:

Есть хороший потенциал для дальнейшей оптимизации. Например, при данной строке и шрифте можно один раз подсчитать и запомнить варианты отображения с их размерами, и просто подбирать наибольший вписывающийся.