How in DataGridTextColumn implement the transition to the exponential record, when there is not enough space to display the full number.

Desired effect:

enter image description here

There is an idea to use a converter, and call it whenever the column width changes. In the converter use StringFormat . Additional questions arise:

  • for which event you need to subscribe which would track the resizing of the column?
  • How to determine how many characters fit into a cell in order to know how many characters to display after the comma and before E ?

PS Something like this makes the TextTrimming="CharacterEllipsis" property of a TextBlock. if there is not enough space to display, some of the characters are replaced by ellipsis. If you find out in what way the TextBlock determines that it does not have enough space to display the text, then you may be able to resolve this issue.

  • one
    In theory, here rests on the custom control and DataGridTemplateColumn. This may be a TextBlock heir or an attached property, which, when resized, will somehow determine that the content does not fit and changes the record. So it remains to find out this "somehow" - vitidev
  • The whole question is what event to subscribe so that you can track the width of the column. Did you find this event? - Bulson
  • @Bulson, in the process, I will unsubscribe if I find it. - Gardes
  • I have already found ... but I haven’t yet added how to calculate the required width for the required number of characters. If you want, I can put it in the answer, but the answer is still not, because no end result. - Bulson
  • @Bulson, lay out, and then the answer can be supplemented. - Gardes

1 answer 1

In theory, for this you can adjust the UserControl and a little code-behind. To measure the width of the text without displaying suitable class FormattedText . Here is a simple sketch:

Control:

 <UserControl x:Class="Test.DoubleWidthFitControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <TextBlock Name="Target" HorizontalAlignment="Right"/> </UserControl> 

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; } } 

It’s easy to use:

 <local:DoubleWidthFitControl Value="10000000000" /> 

Result:

animated cartoon

There is a good potential for further optimization. For example, with a given line and a font, you can once calculate and remember the display options with their sizes, and simply select the largest one that fits.

  • Great! I wonder how the application will behave if you put such custom control into each DataGrid cell. - Gardes
  • @ S.Kost: I hope it will not slow down much :) If you will, you need to look towards optimizations, yes. // Glad to be helpful. - VladD
  • and why Measure is not a local function? :-) - Grundy
  • @Grundy: Hmm, really :) - VladD