Как в 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;
}
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;
}
}
Использовать просто:
Результат:
Есть хороший потенциал для дальнейшей оптимизации. Например, при данной строке и шрифте можно один раз подсчитать и запомнить варианты отображения с их размерами, и просто подбирать наибольший вписывающийся.
Комментариев нет:
Отправить комментарий