From 62cf21d57170aa6c624d4747fe32b403f40dbd36 Mon Sep 17 00:00:00 2001 From: Raphael Noeldner Date: Mon, 20 Mar 2023 13:18:11 +0100 Subject: [PATCH] Replaced slow method of calculating column with with faster method. --- .../UserInterfaceSettings/ViewSettings.cs | 2 +- Library/SharedAssemblyInfo.cs | 6 +- Library/WinFormControls/DetailControl.cs | 10 +- .../WinFormControls/FilteredDataGridView.cs | 110 +++++++++++++----- 4 files changed, 91 insertions(+), 37 deletions(-) diff --git a/Library/ClassLibraryCSV/UserInterfaceSettings/ViewSettings.cs b/Library/ClassLibraryCSV/UserInterfaceSettings/ViewSettings.cs index bc013ffc..568d04e3 100644 --- a/Library/ClassLibraryCSV/UserInterfaceSettings/ViewSettings.cs +++ b/Library/ClassLibraryCSV/UserInterfaceSettings/ViewSettings.cs @@ -300,7 +300,7 @@ public bool WarnEmptyTailingColumns set => SetProperty(ref m_WarnEmptyTailingColumns, value); } - [DefaultValue(2000)] + [DefaultValue(500)] public int ShowButtonAtLength { get => m_ShowButtonAtLength; diff --git a/Library/SharedAssemblyInfo.cs b/Library/SharedAssemblyInfo.cs index 57627225..df1263fc 100644 --- a/Library/SharedAssemblyInfo.cs +++ b/Library/SharedAssemblyInfo.cs @@ -11,6 +11,6 @@ // Version information for an assembly consists of the following four values: Major Version Minor // Version Build Number Revision You can specify all the values or you can default the Build and.Json // Revision Numbers by using the '*' as shown below: [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.5.580")] -[assembly: AssemblyFileVersion("1.7.5.580")] -[assembly: AssemblyInformationalVersion("1.7.5.580")] // a.k.a. "Product version" \ No newline at end of file +[assembly: AssemblyVersion("1.7.5.581")] +[assembly: AssemblyFileVersion("1.7.5.581")] +[assembly: AssemblyInformationalVersion("1.7.5.581")] // a.k.a. "Product version" \ No newline at end of file diff --git a/Library/WinFormControls/DetailControl.cs b/Library/WinFormControls/DetailControl.cs index 87b94018..3ecad679 100644 --- a/Library/WinFormControls/DetailControl.cs +++ b/Library/WinFormControls/DetailControl.cs @@ -98,7 +98,7 @@ public DetailControl() [Bindable(false)] [Browsable(true)] - [DefaultValue(2000)] + [DefaultValue(500)] public int ShowButtonAtLength { get => FilteredDataGridView.ShowButtonAtLength; set => FilteredDataGridView.ShowButtonAtLength = value; } /// @@ -402,13 +402,9 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - private void AutoResizeColumns(DataTable source) + private void AutoResizeColumns() { - if (source.Rows.Count < 10000 && source.Columns.Count < 50) - FilteredDataGridView.AutoResizeColumns( - source.Rows.Count < 1000 && source.Columns.Count < 20 - ? DataGridViewAutoSizeColumnsMode.AllCells - : DataGridViewAutoSizeColumnsMode.DisplayedCells); + FilteredDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); } private void searchBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) diff --git a/Library/WinFormControls/FilteredDataGridView.cs b/Library/WinFormControls/FilteredDataGridView.cs index 26780aa8..6ebc373d 100644 --- a/Library/WinFormControls/FilteredDataGridView.cs +++ b/Library/WinFormControls/FilteredDataGridView.cs @@ -45,7 +45,7 @@ public partial class FilteredDataGridView : DataGridView private bool m_DisposedValue; private IFileSetting? m_FileSetting; - private int m_ShowButtonAtLength = 2000; + private int m_ShowButtonAtLength = 1000; private int m_MenuItemColumnIndex; private void PassOnFontChanges(object? sender, EventArgs e) @@ -126,8 +126,7 @@ public FilteredDataGridView() FontChanged += (_, _) => { AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells; - AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells; - AutoSize = true; + AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); }; } @@ -150,14 +149,13 @@ public FilteredDataGridView() [Bindable(true)] [Browsable(true)] - [DefaultValue(2000)] + [DefaultValue(500)] public int ShowButtonAtLength { get => m_ShowButtonAtLength; set { - var newVal = value < 0 ? 0 : value; - + var newVal = value < 10 ? 10 : value; if (m_ShowButtonAtLength == newVal) return; m_ShowButtonAtLength = newVal; @@ -663,35 +661,95 @@ private static string DefFileNameColSetting(IFileSetting fileSetting, string ext /// /// /// A number for DataGridViewColumn.With - private static int GetColumnWith(DataColumn col, DataRowCollection rowCollection) + private int GetColumnWith(DataColumn col, DataRowCollection rowCollection) { + using var grap = CreateGraphics(); + + if (col.DataType == typeof(Guid)) + return Math.Max(TextRenderer.MeasureText(grap, "4B3D8135-5EA3-4AFC-A912-A768BDB4795E", Font).Width, + TextRenderer.MeasureText(grap, col.ColumnName, Font).Width)+ 5; + if (col.DataType == typeof(int) || col.DataType == typeof(bool) || col.DataType == typeof(long)) - return 25; + return Math.Max(TextRenderer.MeasureText(grap, "626727278", Font).Width, + TextRenderer.MeasureText(grap, col.ColumnName, Font).Width)+ 5; + if (col.DataType == typeof(decimal)) - return 50; + return Math.Max(TextRenderer.MeasureText(grap, "626727278.4664", Font).Width, TextRenderer.MeasureText(grap, col.ColumnName, Font).Width)+ 5; + if (col.DataType == typeof(DateTime)) - return 110; + { + var maxLen = TextRenderer.MeasureText(grap, col.ColumnName, Font).Width; + var counter = 0; + var lastIncrease = 0; + foreach (DataRow dataRow in rowCollection) + { + if (dataRow[col] is DateTime dtm) + { + var len = TextRenderer.MeasureText(grap, StringConversion.DisplayDateTime(dtm, CultureInfo.CurrentCulture), Font).Width; + if (len>maxLen) + { + lastIncrease= counter; + maxLen = len; + } + + } + if (counter > 20000 || counter-lastIncrease > 500) + break; + counter++; + + } + return maxLen + 5; + } + + if (col.DataType == typeof(string)) { + var maxLen = TextRenderer.MeasureText(grap, col.ColumnName, Font).Width; + var counter = 0; + var lastIncrease = 0; foreach (DataRow dataRow in rowCollection) { - var value = dataRow[col]; - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - if (value is null) + var textLen = dataRow[col]?.ToString()?.Length ?? 0; + if (textLen ==0) continue; -#pragma warning disable CS8602 // Dereference of a possibly null reference. - switch (value.ToString().Length) + if (textLen > m_ShowButtonAtLength) + return Math.Max(TextRenderer.MeasureText(grap, "Button", Font).Width, + TextRenderer.MeasureText(grap, col.ColumnName, Font).Width) + 5; + + var len = TextRenderer.MeasureText(grap, dataRow[col]!.ToString(), Font).Width; + if (len>maxLen) { - case > 80: - return 350; - case > 15: - return 225; + lastIncrease= counter; + maxLen = len; } -#pragma warning restore CS8602 // Dereference of a possibly null reference. + if (counter > 20000 || counter-lastIncrease > 500 || maxLen>Width/2) + break; + counter++; } + return Math.Min(maxLen, Width/2) + 5; } - return 100; + return Math.Max(TextRenderer.MeasureText(grap, "dummy", Font).Width, TextRenderer.MeasureText(grap, col.ColumnName, Font).Width); + } + + public new void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode) + { + if (DataView == null) + base.AutoResizeColumns(autoSizeColumnsMode); + else + { + foreach (DataColumn col in DataView!.Table.Columns) + { + foreach (DataGridViewColumn newColumn in Columns) + { + if (newColumn.DataPropertyName == col.ColumnName) + { + newColumn.Width = GetColumnWith(col, DataView!.Table.Rows); + break; + } + } + } + } } // To detect redundant calls @@ -977,10 +1035,10 @@ private void GenerateDataGridViewColumn() if (wrapColumns.Contains(col)) newColumn.DefaultCellStyle.WrapMode = DataGridViewTriState.True; - - newColumn.Width = oldWith.TryGetValue(newColumn.DataPropertyName, out var value) && !showAsButton.Contains(col) ? - value : showAsButton.Contains(col) ? 25 : GetColumnWith(col, DataView.Table.Rows); - + newColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; + newColumn.Width = + oldWith.TryGetValue(newColumn.DataPropertyName, out var value) ? value : + GetColumnWith(col, DataView.Table.Rows); Columns.Add(newColumn); } } @@ -1419,7 +1477,7 @@ private async void ToolStripMenuItemSaveCol_Click(object? sender, EventArgs e) #endif // ReSharper disable once UseAwaitUsing using var stream = new ImprovedStream(new SourceAccess(fileName, false)); -#if NET5_0_OR_GREATER +#if NET5_0_OR_GREATER await #endif using var writer = new StreamWriter(stream, Encoding.UTF8, 1024);