diff --git a/Documents/Changelog/Changelog.md b/Documents/Changelog/Changelog.md
index 2047e26768..9212dd865f 100644
--- a/Documents/Changelog/Changelog.md
+++ b/Documents/Changelog/Changelog.md
@@ -45,6 +45,7 @@
## 2026-11-xx - Build 2611 (V110 Nightly) - November 2026
+* Implemented [#3301](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3301), Is it time to bring over `AdvancedDataGridView`
* Resolved [#3164](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3164), Font properties with no explicit value were not correctly serialized/deserialized in exported XML
* Resolved [#3183](https://github.com/Krypton-Suite/Standard-Toolkit/issues/3183), Small square rendered next to Close button on KryptonForm when using a custom theme
* Implemented [#908](https://github.com/Krypton-Suite/Standard-Toolkit/issues/908), Create new items via 'New Item/Project'
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs
new file mode 100644
index 0000000000..821f516592
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridView.cs
@@ -0,0 +1,1520 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+// Control specific using statements
+
+#if NETFRAMEWORK
+using System.Web.Script.Serialization;
+#else
+using System.Text.Json;
+#endif
+
+namespace Krypton.Utilities;
+
+///
+/// Extends with Excel-style column filtering, multi-column sort composition,
+/// and optional integration with for in-grid search.
+///
+///
+///
+/// Filter and sort are applied by composing expressions and assigning them to the data source:
+/// / when is a ;
+/// / when it is a ;
+/// or row filter and sort when it is a (non-null default view).
+///
+///
+/// Use and to observe changes; set or to skip updating the bound source.
+///
+///
+///
+///
+/// KryptonAdvancedDataGridView developer guide
+[DesignerCategory("code")]
+public class KryptonAdvancedDataGridView : KryptonDataGridView
+{
+ #region Instance Fields
+
+ private readonly List _sortOrderList = [];
+ private readonly List _filterOrderList = [];
+ private readonly List _filteredColumns = [];
+ private List _menuStripToDispose = [];
+
+ private bool _loadedFilter;
+ private string? _sortString;
+ private string? _filterString;
+
+ private bool _sortStringChangedInvokeBeforeDatasourceUpdate = true;
+ private bool _filterStringChangedInvokeBeforeDatasourceUpdate = true;
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Provides data for .
+ ///
+ public class SortEventArgs : EventArgs
+ {
+ ///
+ /// Gets or sets the composed ADO.NET-style sort expression for the bound list (e.g. ).
+ ///
+ public string? SortString { get; set; }
+
+ ///
+ /// When , the control does not assign the sort to the data source.
+ ///
+ public bool Cancel { get; set; }
+
+ /// Initializes a new instance of the class.
+ public SortEventArgs()
+ {
+ SortString = null;
+ Cancel = false;
+ }
+ }
+
+ ///
+ /// Provides data for .
+ ///
+ public class FilterEventArgs : EventArgs
+ {
+ ///
+ /// Gets or sets the composed row filter expression (e.g. or ).
+ ///
+ public string? FilterString { get; set; }
+
+ ///
+ /// When , the control does not assign the filter to the data source.
+ ///
+ public bool Cancel { get; set; }
+
+ /// Initializes a new instance of the class.
+ public FilterEventArgs()
+ {
+ FilterString = null;
+ Cancel = false;
+ }
+ }
+
+ ///
+ /// Occurs when the aggregate sort expression changes, before or after the data source is updated depending on .
+ ///
+ public event EventHandler? SortStringChanged;
+
+ ///
+ /// Occurs when the aggregate filter expression changes, before or after the data source is updated depending on .
+ ///
+ public event EventHandler? FilterStringChanged;
+
+ #endregion
+
+ #region Identity
+
+ /// Initializes a new instance of the class.
+ public KryptonAdvancedDataGridView()
+ {
+ //System.Windows.Forms.RightToLeft = System.Windows.Forms.RightToLeft.No;
+ }
+
+ #endregion
+
+ #region Implementation
+
+ ///
+ /// Default UI strings for column header menus and the custom filter dialog. Keys are the string names of members (for example nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending)).
+ /// Merge overrides with or .
+ ///
+ public static Dictionary Translations = new()
+ {
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeAscending), "Sort Oldest to Newest" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeDescending), "Sort Newest to Oldest" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolAscending), "Sort by False/True" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolDescending), "Sort by True/False" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumAscending), "Sort Smallest to Largest" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumDescending), "Sort Largest to Smallest" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending), "Sort А to Z" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextDescending), "Sort Z to A" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewAddCustomFilter), "Add a Custom Filter" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter), "Custom Filter" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewClearFilter), "Clear Filter" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewClearSort), "Clear Sort" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonFilter), "Filter" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonUndoFilter), "Cancel" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll), "(Select All)" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty), "(Blanks)" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectTrue), "True" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectFalse), "False" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewFilterChecklistDisable), "Filter list is disabled" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewEquals), "equals" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual), "does not equal" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan), "earlier than" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo), "earlier than or equal to" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan), "later than"},
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo), "later than or equal to" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewBetween), "between" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan), "greater than" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo), "greater than or equal to" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan), "less than" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo), "less than or equal to" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith), "begins with" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith), "does not begin with" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith), "ends with" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith), "does not end with" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewContains), "contains" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain), "does not contain" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewInvalidValue), "Invalid Value" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewFilterStringDescription), "Show rows where value {0} \"{1}\"" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewFormTitle), "Custom Filter" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLabelColumnNameText), "Show rows where value" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewLabelAnd), "And" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonOk), "OK" },
+ { nameof(TranslationKey.KryptonAdvancedDataGridViewButtonCancel), "Cancel" }
+ };
+
+ #endregion
+
+ #region Implemntation
+
+ #region translations methods
+
+ ///
+ /// Merges entries into for keys that already exist; unknown keys are ignored.
+ ///
+ /// Localized strings, keyed by the same names as .
+ public static void SetTranslations(IDictionary? translations)
+ {
+ //set localization strings
+ if (translations != null)
+ {
+ foreach (KeyValuePair translation in translations)
+ {
+ if (Translations.ContainsKey(translation.Key))
+ {
+ Translations[translation.Key] = translation.Value;
+ }
+ }
+ }
+ }
+
+ /// Returns the live dictionary.
+ /// The static translation map used by filter and sort UI.
+ public static IDictionary GetTranslations()
+ {
+ return Translations;
+ }
+
+ ///
+ /// Loads a JSON object of string keys and string values, merges recognized keys, and fills any missing keys from .
+ ///
+ /// Path to the JSON file.
+ /// A new dictionary suitable for passing to .
+ public static IDictionary LoadTranslationsFromFile(string filename)
+ {
+ IDictionary ret = new Dictionary();
+
+ if (!String.IsNullOrEmpty(filename))
+ {
+ //deserialize the file
+ try
+ {
+ string jsonText = File.ReadAllText(filename);
+#if NETFRAMEWORK
+ Dictionary translations =
+ new JavaScriptSerializer().Deserialize>(jsonText);
+#else
+ Dictionary? translations =
+ JsonSerializer.Deserialize>(jsonText);
+#endif
+ foreach (KeyValuePair translation in translations!)
+ {
+ if (!ret.ContainsKey(translation.Key) && Translations.ContainsKey(translation.Key))
+ {
+ ret.Add(translation.Key, translation.Value);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ KryptonExceptionHandler.CaptureException(e);
+ }
+ }
+
+ //add default translations if not in files
+ foreach (KeyValuePair translation in GetTranslations())
+ {
+ if (!ret.ContainsKey(translation.Key))
+ {
+ ret.Add(translation.Key, translation.Value);
+ }
+ }
+
+ return ret;
+ }
+
+ #endregion
+
+
+ #region public Helper methods
+
+ /// Sets to to reduce flicker.
+ public void SetDoubleBuffered()
+ {
+ DoubleBuffered = true;
+ }
+
+ #endregion
+
+
+ #region public Filter and Sort methods
+
+ ///
+ /// Gets or sets whether is raised before (default) or after the sort is applied to the data source.
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool SortStringChangedInvokeBeforeDatasourceUpdate
+ {
+ get => _sortStringChangedInvokeBeforeDatasourceUpdate;
+ set => _sortStringChangedInvokeBeforeDatasourceUpdate = value;
+ }
+
+ ///
+ /// Gets or sets whether is raised before (default) or after the filter is applied to the data source.
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool FilterStringChangedInvokeBeforeDatasourceUpdate
+ {
+ get => _filterStringChangedInvokeBeforeDatasourceUpdate;
+ set => _filterStringChangedInvokeBeforeDatasourceUpdate = value;
+ }
+
+ ///
+ /// Disable a Filter and Sort on a DataGridViewColumn
+ ///
+ ///
+ public void DisableFilterAndSort(DataGridViewColumn column)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ if (cell.FilterAndSortEnabled && (cell.SortString!.Length > 0 || cell.FilterString!.Length > 0))
+ {
+ CleanFilter(true);
+ cell.FilterAndSortEnabled = false;
+ }
+ else
+ {
+ cell.FilterAndSortEnabled = false;
+ }
+
+ _filterOrderList.Remove(column.Name);
+ _sortOrderList.Remove(column.Name);
+ _filteredColumns.Remove(column.Name);
+ }
+ }
+ }
+
+ ///
+ /// Enable a Filter and Sort on a DataGridViewColumn
+ ///
+ ///
+ public void EnableFilterAndSort(DataGridViewColumn column)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ if (!cell.FilterAndSortEnabled && (cell.FilterString!.Length > 0 || cell.SortString!.Length > 0))
+ {
+ CleanFilter(true);
+ }
+
+ cell.FilterAndSortEnabled = true;
+ _filteredColumns.Remove(column.Name);
+
+ SetFilterDateAndTimeEnabled(column, cell.IsFilterDateAndTimeEnabled);
+ SetSortEnabled(column, cell.IsSortEnabled);
+ SetFilterEnabled(column, cell.IsFilterEnabled);
+ }
+ else
+ {
+ column.SortMode = DataGridViewColumnSortMode.Programmatic;
+ cell = new KryptonColumnHeaderCell(column.HeaderCell, true);
+ cell.SortChanged += Cell_SortChanged;
+ cell.FilterChanged += Cell_FilterChanged;
+ cell.FilterPopup += Cell_FilterPopup;
+ column.MinimumWidth = cell.MinimumSize.Width;
+ if (ColumnHeadersHeight < cell.MinimumSize.Height)
+ {
+ ColumnHeadersHeight = cell.MinimumSize.Height;
+ }
+
+ column.HeaderCell = cell;
+ }
+ }
+ }
+
+ ///
+ /// Enabled or disable Filter and Sort capabilities on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterAndSortEnabled(DataGridViewColumn column, bool enabled)
+ {
+ if (enabled)
+ {
+ EnableFilterAndSort(column);
+ }
+ else
+ {
+ DisableFilterAndSort(column);
+ }
+ }
+
+ ///
+ /// Disable a Filter checklist on a DataGridViewColumn
+ ///
+ ///
+ public void DisableFilterChecklist(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterChecklistEnabled(false);
+ }
+ }
+ }
+
+ ///
+ /// Enable a Filter checklist on a DataGridViewColumn
+ ///
+ ///
+ public void EnableFilterChecklist(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterChecklistEnabled(true);
+ }
+ }
+ }
+
+ ///
+ /// Enabled or disable Filter checklist capabilities on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterChecklistEnabled(DataGridViewColumn? column, bool enabled)
+ {
+ if (enabled)
+ {
+ EnableFilterChecklist(column);
+ }
+ else
+ {
+ DisableFilterChecklist(column);
+ }
+ }
+
+ ///
+ /// Set Filter checklist nodes max on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterChecklistNodesMax(DataGridViewColumn column, int maxNodes)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterChecklistNodesMax(maxNodes);
+ }
+ }
+ }
+
+ ///
+ /// Set Filter checklist nodes max
+ ///
+ ///
+ public void SetFilterChecklistNodesMax(int maxNodes)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.SetFilterChecklistNodesMax(maxNodes);
+ }
+ }
+
+ ///
+ /// Enable or disable Filter checklist nodes max on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void EnabledFilterChecklistNodesMax(DataGridViewColumn column, bool enabled)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.EnabledFilterChecklistNodesMax(enabled);
+ }
+ }
+ }
+
+ ///
+ /// Enable or disable Filter checklist nodes max
+ ///
+ ///
+ public void EnabledFilterChecklistNodesMax(bool enabled)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.EnabledFilterChecklistNodesMax(enabled);
+ }
+ }
+
+ ///
+ /// Disable a Filter custom on a DataGridViewColumn
+ ///
+ ///
+ public void DisableFilterCustom(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterCustomEnabled(false);
+ }
+ }
+ }
+
+ ///
+ /// Enable a Filter custom on a DataGridViewColumn
+ ///
+ ///
+ public void EnableFilterCustom(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterCustomEnabled(true);
+ }
+ }
+ }
+
+ ///
+ /// Enabled or disable Filter custom capabilities on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterCustomEnabled(DataGridViewColumn? column, bool enabled)
+ {
+ if (enabled)
+ {
+ EnableFilterCustom(column);
+ }
+ else
+ {
+ DisableFilterCustom(column);
+ }
+ }
+
+ ///
+ /// Set nodes to enable TextChanged delay on filter checklist on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayNodes(DataGridViewColumn? column, int numNodes)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.TextFilterTextChangedDelayNodes = numNodes;
+ }
+ }
+ }
+
+ ///
+ /// Set nodes to enable TextChanged delay on filter checklist
+ ///
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayNodes(int numNodes)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.TextFilterTextChangedDelayNodes = numNodes;
+ }
+ }
+
+ ///
+ /// Disable TextChanged delay on filter checklist on a DataGridViewColumn
+ ///
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayDisabled(DataGridViewColumn column)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetTextFilterTextChangedDelayNodesDisabled();
+ }
+ }
+ }
+
+ ///
+ /// Disable TextChanged delay on filter checklist
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayDisabled()
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.SetTextFilterTextChangedDelayNodesDisabled();
+ }
+ }
+
+ ///
+ /// Set TextChanged delay milliseconds on filter checklist on a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayMs(DataGridViewColumn? column, int milliseconds)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetTextFilterTextChangedDelayMs(milliseconds);
+ }
+ }
+ }
+
+ ///
+ /// Set TextChanged delay milliseconds on filter checklist
+ ///
+ public void SetFilterChecklistTextFilterTextChangedDelayMs(int milliseconds)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.SetTextFilterTextChangedDelayMs(milliseconds);
+ }
+ }
+
+ ///
+ /// Applies saved filter and sort expressions and marks header cells as loaded until the user changes filter state.
+ ///
+ /// Aggregate filter string, or to skip.
+ /// Aggregate sort string, or to skip.
+ public void LoadFilterAndSort(string? filter, string? sorting)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.SetLoadedMode(true);
+ }
+
+ _filteredColumns.Clear();
+
+ _filterOrderList.Clear();
+ _sortOrderList.Clear();
+
+ if (filter != null)
+ {
+ FilterString = filter;
+ }
+
+ if (sorting != null)
+ {
+ SortString = sorting;
+ }
+
+ _loadedFilter = true;
+ }
+
+ /// Clears loaded mode, internal order lists, and all column filter and sort state.
+ public void CleanFilterAndSort()
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.SetLoadedMode(false);
+ }
+
+ _filteredColumns.Clear();
+ _filterOrderList.Clear();
+ _sortOrderList.Clear();
+
+ _loadedFilter = false;
+
+ CleanFilter();
+ CleanSort();
+ }
+
+ ///
+ /// Enables or disables NOT IN-style semantics for checklist filters on all filterable columns.
+ ///
+ /// to use NOT IN logic; otherwise .
+ public void SetMenuStripFilterNotInLogic(bool enabled)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.IsMenuStripFilterNOTINLogicEnabled = enabled;
+ }
+ }
+
+ ///
+ /// Gets or sets whether new columns receive filter and sort UI. Also used when replacing header cells in .
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool FilterAndSortEnabled
+ {
+ get => _filterAndSortEnabled;
+ set => _filterAndSortEnabled = value;
+ }
+ private bool _filterAndSortEnabled = true;
+
+ private bool _filterAndSortOnBitmapColumns;
+
+ ///
+ /// Gets or sets whether filter and sort UI is shown on columns whose is .
+ /// Default is (image columns have no header drop-down).
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool FilterAndSortOnBitmapColumns
+ {
+ get => _filterAndSortOnBitmapColumns;
+ set
+ {
+ if (_filterAndSortOnBitmapColumns == value)
+ {
+ return;
+ }
+
+ _filterAndSortOnBitmapColumns = value;
+ for (int i = 0; i < Columns.Count; i++)
+ {
+ InvalidateCell(i, -1);
+ }
+ }
+ }
+
+ #endregion
+
+
+ #region public Sort methods
+
+ ///
+ /// Gets the composed multi-column sort expression. Applied to ,
+ /// , or when the data source matches.
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string? SortString
+ {
+ get => !string.IsNullOrEmpty(_sortString) ? _sortString : string.Empty;
+ private set
+ {
+ string? old = value;
+ if (old != _sortString)
+ {
+ _sortString = value;
+
+ TriggerSortStringChanged();
+ }
+ }
+ }
+
+ ///
+ /// Raises (subject to ) and applies the current sort to the data source when not canceled.
+ ///
+ public void TriggerSortStringChanged()
+ {
+ //call event handler if one is attached
+ SortEventArgs sortEventArgs = new SortEventArgs
+ {
+ SortString = _sortString,
+ Cancel = false
+ };
+ //invoke SortStringChanged
+ if (_sortStringChangedInvokeBeforeDatasourceUpdate)
+ {
+ if (SortStringChanged != null)
+ {
+ SortStringChanged.Invoke(this, sortEventArgs);
+ }
+ }
+ //sort datasource
+ if (sortEventArgs.Cancel == false)
+ {
+ if (DataSource is BindingSource datasource)
+ {
+ datasource.Sort = sortEventArgs.SortString;
+ }
+ else if (DataSource is DataView dataView)
+ {
+ dataView.Sort = sortEventArgs.SortString ?? string.Empty;
+ }
+ else if (DataSource is DataTable { DefaultView: not null } dataTable)
+ {
+ dataTable.DefaultView.Sort = sortEventArgs.SortString ?? string.Empty;
+ }
+ }
+ //invoke SortStringChanged
+ if (!_sortStringChangedInvokeBeforeDatasourceUpdate)
+ {
+ if (SortStringChanged != null)
+ {
+ SortStringChanged.Invoke(this, sortEventArgs);
+ }
+ }
+ }
+
+ ///
+ /// Enabled or disable Sort capabilities for a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetSortEnabled(DataGridViewColumn? column, bool enabled)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetSortEnabled(enabled);
+ }
+ }
+ }
+
+ ///
+ /// Applies ascending sort for the column via the header menu logic.
+ ///
+ /// The column to sort, or to no-op.
+ public void SortAscending(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SortASC();
+ }
+ }
+ }
+
+ ///
+ /// Applies descending sort for the column via the header menu logic.
+ ///
+ /// The column to sort, or to no-op.
+ public void SortDescending(DataGridViewColumn? column)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SortDESC();
+ }
+ }
+ }
+
+ ///
+ /// Clean all Sort on specific column
+ ///
+ ///
+ ///
+ public void CleanSort(DataGridViewColumn? column, bool fireEvent)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell && FilterableCells.Contains(cell))
+ {
+ cell.CleanSort();
+ //remove column from sorted list
+ _sortOrderList.Remove(column.Name);
+ }
+ }
+
+ if (fireEvent)
+ {
+ SortString = BuildSortString();
+ }
+ else
+ {
+ _sortString = BuildSortString();
+ }
+ }
+
+ ///
+ /// Clean all Sort on specific column
+ ///
+ ///
+ public void CleanSort(DataGridViewColumn? column)
+ {
+ CleanSort(column, true);
+ }
+
+ ///
+ /// Clean all Sort on all columns
+ ///
+ ///
+ public void CleanSort(bool fireEvent)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.CleanSort();
+ }
+
+ _sortOrderList.Clear();
+
+ if (fireEvent)
+ {
+ SortString = null;
+ }
+ else
+ {
+ _sortString = null;
+ }
+ }
+
+ ///
+ /// Clean all Sort on all columns
+ ///
+ public void CleanSort()
+ {
+ CleanSort(true);
+ }
+
+ #endregion
+
+
+ #region public Filter methods
+
+ ///
+ /// Gets the composed row filter (multi-column conditions combined with AND). Applied to , , or the table default view when supported.
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string? FilterString
+ {
+ get => !String.IsNullOrEmpty(_filterString) ? _filterString : "";
+ private set
+ {
+ string? old = value;
+ if (old != _filterString)
+ {
+ _filterString = value;
+
+ TriggerFilterStringChanged();
+ }
+ }
+ }
+
+ ///
+ /// Raises (subject to ) and applies the current filter to the data source when not canceled.
+ ///
+ public void TriggerFilterStringChanged()
+ {
+ //call event handler if one is attached
+ FilterEventArgs filterEventArgs = new FilterEventArgs
+ {
+ FilterString = _filterString,
+ Cancel = false
+ };
+ //invoke FilterStringChanged
+ if (_filterStringChangedInvokeBeforeDatasourceUpdate)
+ {
+ if (FilterStringChanged != null)
+ {
+ FilterStringChanged.Invoke(this, filterEventArgs);
+ }
+ }
+ //filter datasource
+ if (filterEventArgs.Cancel == false)
+ {
+ if (DataSource is BindingSource bindingsource)
+ {
+ bindingsource.Filter = filterEventArgs.FilterString;
+ }
+ else if (DataSource is DataView dataview)
+ {
+ dataview.RowFilter = filterEventArgs.FilterString;
+ }
+ else if (DataSource is DataTable { DefaultView: not null } datatable)
+ {
+ datatable.DefaultView.RowFilter = filterEventArgs.FilterString;
+ }
+ }
+ //invoke FilterStringChanged
+ if (!_filterStringChangedInvokeBeforeDatasourceUpdate)
+ {
+ if (FilterStringChanged != null)
+ {
+ FilterStringChanged.Invoke(this, filterEventArgs);
+ }
+ }
+ }
+
+ ///
+ /// Set FilterDateAndTime status for a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterDateAndTimeEnabled(DataGridViewColumn? column, bool enabled)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.IsFilterDateAndTimeEnabled = enabled;
+ }
+ }
+ }
+
+ ///
+ /// Enable or disable Filter capabilities for a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetFilterEnabled(DataGridViewColumn column, bool enabled)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetFilterEnabled(enabled);
+ }
+ }
+ }
+
+ ///
+ /// Enable or disable Text filter on checklist remove node mode for a DataGridViewColumn
+ ///
+ ///
+ ///
+ public void SetChecklistTextFilterRemoveNodesOnSearchMode(DataGridViewColumn? column, bool enabled)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SetChecklistTextFilterRemoveNodesOnSearchMode(enabled);
+ }
+ }
+ }
+
+ ///
+ /// Clean Filter on specific column
+ ///
+ ///
+ ///
+ public void CleanFilter(DataGridViewColumn column, bool fireEvent)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.CleanFilter();
+ //remove column from filtered list
+ _filterOrderList.Remove(column.Name);
+ }
+ }
+
+ if (fireEvent)
+ {
+ FilterString = BuildFilterString();
+ }
+ else
+ {
+ _filterString = BuildFilterString();
+ }
+ }
+
+ ///
+ /// Clean Filter on specific column
+ ///
+ ///
+ public void CleanFilter(DataGridViewColumn column)
+ {
+ CleanFilter(column, true);
+ }
+
+ ///
+ /// Clean Filter on all columns
+ ///
+ ///
+ public void CleanFilter(bool fireEvent)
+ {
+ foreach (KryptonColumnHeaderCell c in FilterableCells)
+ {
+ c.CleanFilter();
+ }
+ _filterOrderList.Clear();
+
+ if (fireEvent)
+ {
+ FilterString = null;
+ }
+ else
+ {
+ _filterString = null;
+ }
+ }
+
+ /// Clears filters on all columns and raises the aggregate filter change.
+ public void CleanFilter()
+ {
+ CleanFilter(true);
+ }
+
+ ///
+ /// Set the text filter search nodes behaviour
+ ///
+ public void SetTextFilterRemoveNodesOnSearch(DataGridViewColumn? column, bool enabled)
+ {
+ if (column != null && Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.DoesTextFilterRemoveNodesOnSearch = enabled;
+ }
+ }
+ }
+
+ ///
+ /// Get the text filter search nodes behaviour
+ ///
+ public bool? GetTextFilterRemoveNodesOnSearch(DataGridViewColumn column)
+ {
+ bool? ret = null;
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ ret = cell.DoesTextFilterRemoveNodesOnSearch;
+ }
+ }
+ return ret;
+ }
+
+ #endregion
+
+
+ #region public Find methods
+
+ ///
+ /// Searches displayed cell text from a start position; typically used with for find-next behavior.
+ ///
+ /// Text to match against .
+ /// Bound column to search, or to search all visible columns.
+ /// Starting row index (clamped to zero or greater).
+ /// Starting column index when searching all columns.
+ /// When , requires an exact match of the formatted string.
+ /// When , comparison is case-sensitive.
+ /// The first matching cell, or if none.
+ public DataGridViewCell? FindCell(string? valueToFind, string? columnName, int rowIndex, int columnIndex, bool isWholeWordSearch, bool isCaseSensitive)
+ {
+ if (valueToFind != null && RowCount > 0 && ColumnCount > 0 && (columnName == null || (Columns.Contains(columnName) && Columns[columnName]!.Visible)))
+ {
+ rowIndex = Math.Max(0, rowIndex);
+
+ if (!isCaseSensitive)
+ {
+ valueToFind = valueToFind.ToLower();
+ }
+
+ if (columnName != null)
+ {
+ int c = Columns[columnName]!.Index;
+ if (columnIndex > c)
+ {
+ rowIndex++;
+ }
+
+ for (int r = rowIndex; r < RowCount; r++)
+ {
+ string value = Rows[r].Cells[c].FormattedValue?.ToString() ?? string.Empty;
+ if (!isCaseSensitive)
+ {
+ value = value.ToLower();
+ }
+
+ if ((!isWholeWordSearch && value.Contains(valueToFind)) || value.Equals(valueToFind))
+ {
+ return Rows[r].Cells[c];
+ }
+ }
+ }
+ else
+ {
+ columnIndex = Math.Max(0, columnIndex);
+
+ for (int r = rowIndex; r < RowCount; r++)
+ {
+ for (int c = columnIndex; c < ColumnCount; c++)
+ {
+ if (!Rows[r].Cells[c].Visible)
+ {
+ continue;
+ }
+
+ string value = Rows[r].Cells[c].FormattedValue?.ToString() ?? string.Empty;
+ if (!isCaseSensitive)
+ {
+ value = value.ToLower();
+ }
+
+ if ((!isWholeWordSearch && value.Contains(valueToFind)) || value.Equals(valueToFind))
+ {
+ return Rows[r].Cells[c];
+ }
+ }
+
+ columnIndex = 0;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ #endregion
+
+
+ #region public Cell methods
+
+ /// Opens the filter and sort drop-down for the specified column programmatically.
+ /// The column whose header menu should open.
+ public void ShowMenuStrip(DataGridViewColumn column)
+ {
+ if (Columns.Contains(column))
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ Cell_FilterPopup(cell, new ColumnHeaderCellEventArgs(cell.MenuStrip, column));
+ }
+ }
+ }
+
+ #endregion
+
+
+ #region cells methods
+
+ ///
+ /// Get all columns
+ ///
+ private IEnumerable FilterableCells =>
+ from DataGridViewColumn c in Columns
+ where c.HeaderCell is KryptonColumnHeaderCell
+ select c.HeaderCell as KryptonColumnHeaderCell;
+
+ #endregion
+
+
+ #region column events
+
+ ///
+ /// Overriden OnColumnAdded event
+ ///
+ ///
+ protected override void OnColumnAdded(DataGridViewColumnEventArgs e)
+ {
+ e.Column.SortMode = DataGridViewColumnSortMode.Programmatic;
+ KryptonColumnHeaderCell cell = new KryptonColumnHeaderCell(e.Column.HeaderCell, FilterAndSortEnabled);
+ cell.SortChanged += Cell_SortChanged;
+ cell.FilterChanged += Cell_FilterChanged;
+ cell.FilterPopup += Cell_FilterPopup;
+ e.Column.MinimumWidth = cell.MinimumSize.Width;
+ if (ColumnHeadersHeight < cell.MinimumSize.Height)
+ {
+ ColumnHeadersHeight = cell.MinimumSize.Height;
+ }
+
+ e.Column.HeaderCell = cell;
+
+ base.OnColumnAdded(e);
+ }
+
+ ///
+ /// Overridden OnColumnRemoved event
+ ///
+ ///
+ protected override void OnColumnRemoved(DataGridViewColumnEventArgs e)
+ {
+ _filteredColumns.Remove(e.Column.Name);
+ _filterOrderList.Remove(e.Column.Name);
+ _sortOrderList.Remove(e.Column.Name);
+
+ if (e.Column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SortChanged -= Cell_SortChanged;
+ cell.FilterChanged -= Cell_FilterChanged;
+ cell.FilterPopup -= Cell_FilterPopup;
+
+ cell.CleanEvents();
+ if (!e.Column.IsDataBound)
+ {
+ cell.MenuStrip?.Dispose();
+ }
+ else if (cell.MenuStrip is { } menuStrip)
+ {
+ _menuStripToDispose.Add(menuStrip);
+ }
+ }
+ base.OnColumnRemoved(e);
+ }
+
+ #endregion
+
+
+ #region rows events
+
+ ///
+ /// Overridden OnRowsAdded event
+ ///
+ ///
+ protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
+ {
+ if (e.RowIndex >= 0)
+ {
+ _filteredColumns.Clear();
+ }
+
+ base.OnRowsAdded(e);
+ }
+
+ ///
+ /// Overridden OnRowsRemoved event
+ ///
+ ///
+ protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
+ {
+ if (e.RowIndex >= 0)
+ {
+ _filteredColumns.Clear();
+ }
+
+ base.OnRowsRemoved(e);
+ }
+
+ #endregion
+
+
+ #region cell events
+
+ ///
+ /// Overridden OnCellValueChanged event
+ ///
+ ///
+ protected override void OnCellValueChanged(DataGridViewCellEventArgs e)
+ {
+ if (e is { RowIndex: >= 0, ColumnIndex: >= 0 })
+ {
+ _filteredColumns.Remove(Columns[e.ColumnIndex].Name);
+ }
+
+ base.OnCellValueChanged(e);
+ }
+
+ #endregion
+
+
+ #region filter events
+
+ ///
+ /// Build the complete Filter string
+ ///
+ ///
+ private string BuildFilterString()
+ {
+ StringBuilder sb = new StringBuilder("");
+ string appx = "";
+
+ foreach (string filterOrder in _filterOrderList)
+ {
+ DataGridViewColumn? column = Columns[filterOrder];
+
+ if (column?.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ if (cell.FilterAndSortEnabled && cell.ActiveFilterType != MenuStrip.FilterType.None)
+ {
+ sb.AppendFormat(appx + "(" + cell.FilterString + ")", column.DataPropertyName);
+ appx = " AND ";
+ }
+ }
+ }
+ return sb.ToString();
+ }
+
+ ///
+ /// FilterPopup event
+ ///
+ ///
+ ///
+ private void Cell_FilterPopup(object sender, ColumnHeaderCellEventArgs e)
+ {
+ if (!Columns.Contains(e.Column) || e.FilterMenu is not { } filterMenu)
+ {
+ return;
+ }
+
+ DataGridViewColumn column = e.Column;
+
+ Rectangle rect = GetCellDisplayRectangle(column.Index, -1, true);
+
+ if (_filteredColumns.Contains(column.Name))
+ {
+ filterMenu.Show(this, rect.Left, rect.Bottom, false);
+ }
+ else
+ {
+ _filteredColumns.Add(column.Name);
+ if (_filterOrderList.Any() && _filterOrderList.Last() == column.Name)
+ {
+ filterMenu.Show(this, rect.Left, rect.Bottom, true);
+ }
+ else
+ {
+ filterMenu.Show(this, rect.Left, rect.Bottom, MenuStrip.GetValuesForFilter(this, column.Name));
+ }
+ }
+ }
+
+ ///
+ /// FilterChanged event
+ ///
+ ///
+ ///
+ private void Cell_FilterChanged(object sender, ColumnHeaderCellEventArgs e)
+ {
+ if (!Columns.Contains(e.Column) || e.FilterMenu is not { } filterMenu)
+ {
+ return;
+ }
+
+ DataGridViewColumn column = e.Column;
+
+ _filterOrderList.Remove(column.Name);
+ if (filterMenu.ActiveFilterType != MenuStrip.FilterType.None)
+ {
+ _filterOrderList.Add(column.Name);
+ }
+
+ FilterString = BuildFilterString();
+
+ if (_loadedFilter)
+ {
+ _loadedFilter = false;
+ foreach (KryptonColumnHeaderCell c in FilterableCells.Where(f => f.MenuStrip != filterMenu))
+ {
+ c.SetLoadedMode(false);
+ }
+ }
+ }
+
+ #endregion
+
+
+ #region sort events
+
+ ///
+ /// Build the complete Sort string
+ ///
+ ///
+ private string BuildSortString()
+ {
+ StringBuilder sb = new StringBuilder("");
+ string appx = "";
+
+ foreach (string sortOrder in _sortOrderList)
+ {
+ DataGridViewColumn? column = Columns[sortOrder];
+
+ if (column?.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ if (cell.FilterAndSortEnabled && cell.ActiveSortType != MenuStrip.SortType.None)
+ {
+ sb.AppendFormat(appx + cell.SortString, column.DataPropertyName);
+ appx = ", ";
+ }
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// SortChanged event
+ ///
+ ///
+ ///
+ private void Cell_SortChanged(object sender, ColumnHeaderCellEventArgs e)
+ {
+ if (!Columns.Contains(e.Column) || e.FilterMenu is not MenuStrip filterMenu)
+ {
+ return;
+ }
+
+ DataGridViewColumn column = e.Column;
+
+ _sortOrderList.Remove(column.Name);
+ if (filterMenu.ActiveSortType != MenuStrip.SortType.None)
+ {
+ _sortOrderList.Add(column.Name);
+ }
+
+ SortString = BuildSortString();
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Protected
+
+ ///
+ protected override void OnHandleDestroyed(EventArgs e)
+ {
+ foreach (DataGridViewColumn column in Columns)
+ {
+ if (column.HeaderCell is KryptonColumnHeaderCell cell)
+ {
+ cell.SortChanged -= Cell_SortChanged;
+ cell.FilterChanged -= Cell_FilterChanged;
+ cell.FilterPopup -= Cell_FilterPopup;
+ }
+ }
+
+ foreach (MenuStrip menuStrip in _menuStripToDispose)
+ {
+ menuStrip.Dispose();
+ }
+
+ _menuStripToDispose.Clear();
+
+ base.OnHandleDestroyed(e);
+ }
+
+ ///
+ protected override void OnDataSourceChanged(EventArgs e)
+ {
+ foreach (DataGridViewColumn column in Columns)
+ {
+ KryptonColumnHeaderCell? cell = column.HeaderCell as KryptonColumnHeaderCell;
+
+ _menuStripToDispose = _menuStripToDispose.Where(f => f != cell!.MenuStrip).ToList();
+ }
+
+ foreach (MenuStrip menuStrip in _menuStripToDispose)
+ {
+ menuStrip.Dispose();
+ }
+
+ _menuStripToDispose.Clear();
+ base.OnDataSourceChanged(e);
+ }
+
+ #endregion
+}
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs
new file mode 100644
index 0000000000..0164dcf231
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/KryptonAdvancedDataGridViewSearchToolBar.cs
@@ -0,0 +1,653 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+// Control specific using statements
+
+#if NETFRAMEWORK
+using System.Web.Script.Serialization;
+#else
+using System.Text.Json;
+#endif
+
+namespace Krypton.Utilities;
+
+[DesignerCategory("code")]
+public partial class KryptonAdvancedDataGridViewSearchToolBar : ToolStrip
+{
+ #region Design Code
+
+ ///
+ /// Required designer variable.
+ ///
+ private IContainer? components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+ if (disposing && components != null)
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.tsbtnClose = new System.Windows.Forms.ToolStripButton();
+ this.tslblSearch = new System.Windows.Forms.ToolStripLabel();
+ this.tscmbColumns = new System.Windows.Forms.ToolStripComboBox();
+ this.tstxtSearch = new System.Windows.Forms.ToolStripTextBox();
+ this.tsbtnFromBegin = new System.Windows.Forms.ToolStripButton();
+ this.tsbtnCaseSensitive = new System.Windows.Forms.ToolStripButton();
+ this.tsbtnSearch = new System.Windows.Forms.ToolStripButton();
+ this.tsbtnWholeWord = new System.Windows.Forms.ToolStripButton();
+ this.tssepSearch = new System.Windows.Forms.ToolStripSeparator();
+ this.SuspendLayout();
+ //
+ // button_close
+ //
+ this.tsbtnClose.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbtnClose.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonCaseSensitive;
+ this.tsbtnClose.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.tsbtnClose.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbtnClose.Name = "tsbtnClose";
+ this.tsbtnClose.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never;
+ this.tsbtnClose.Size = new System.Drawing.Size(23, 24);
+ this.tsbtnClose.Click += new System.EventHandler(this.button_close_Click);
+ //
+ // label_search
+ //
+ this.tslblSearch.Name = "tslblSearch";
+ this.tslblSearch.Size = new System.Drawing.Size(45, 15);
+
+ //
+ // comboBox_columns
+ //
+ this.tscmbColumns.AutoSize = false;
+ this.tscmbColumns.AutoToolTip = true;
+ this.tscmbColumns.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.tscmbColumns.FlatStyle = System.Windows.Forms.FlatStyle.Standard;
+ this.tscmbColumns.IntegralHeight = false;
+ this.tscmbColumns.Margin = new System.Windows.Forms.Padding(0, 2, 8, 2);
+ this.tscmbColumns.MaxDropDownItems = 12;
+ this.tscmbColumns.Name = "tscmbColumns";
+ this.tscmbColumns.Size = new System.Drawing.Size(150, 23);
+ //
+ // textBox_search
+ //
+ this.tstxtSearch.AutoSize = false;
+ this.tstxtSearch.ForeColor = System.Drawing.Color.LightGray;
+ this.tstxtSearch.Margin = new System.Windows.Forms.Padding(0, 2, 8, 2);
+ this.tstxtSearch.Name = "tstxtSearch";
+ this.tstxtSearch.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never;
+ this.tstxtSearch.Size = new System.Drawing.Size(100, 23);
+ this.tstxtSearch.Enter += new System.EventHandler(this.textBox_search_Enter);
+ this.tstxtSearch.Leave += new System.EventHandler(this.textBox_search_Leave);
+ this.tstxtSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox_search_KeyDown);
+ this.tstxtSearch.TextChanged += new System.EventHandler(this.textBox_search_TextChanged);
+ //
+ // button_frombegin
+ //
+ this.tsbtnFromBegin.CheckOnClick = true;
+ this.tsbtnFromBegin.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbtnFromBegin.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonFromBegin;
+ this.tsbtnFromBegin.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.tsbtnFromBegin.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbtnFromBegin.Name = "tsbtnFromBegin";
+ this.tsbtnFromBegin.Size = new System.Drawing.Size(23, 20);
+ //
+ // button_casesensitive
+ //
+ this.tsbtnCaseSensitive.CheckOnClick = true;
+ this.tsbtnCaseSensitive.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbtnCaseSensitive.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonCaseSensitive;
+ this.tsbtnCaseSensitive.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.tsbtnCaseSensitive.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbtnCaseSensitive.Name = "tsbtnCaseSensitive";
+ this.tsbtnCaseSensitive.Size = new System.Drawing.Size(23, 20);
+ //
+ // button_search
+ //
+ this.tsbtnSearch.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbtnSearch.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonSearch;
+ this.tsbtnSearch.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.tsbtnSearch.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbtnSearch.Name = "tsbtnSearch";
+ this.tsbtnSearch.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never;
+ this.tsbtnSearch.Size = new System.Drawing.Size(23, 24);
+ this.tsbtnSearch.Click += new System.EventHandler(this.button_search_Click);
+ //
+ // button_wholeword
+ //
+ this.tsbtnWholeWord.CheckOnClick = true;
+ this.tsbtnWholeWord.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.tsbtnWholeWord.Image = global::Krypton.Utilities.Properties.Resources.SearchToolBar_ButtonWholeWord;
+ this.tsbtnWholeWord.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this.tsbtnWholeWord.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.tsbtnWholeWord.Margin = new System.Windows.Forms.Padding(1, 1, 1, 2);
+ this.tsbtnWholeWord.Name = "tsbtnWholeWord";
+ this.tsbtnWholeWord.Size = new System.Drawing.Size(23, 20);
+ //
+ // separator_search
+ //
+ this.tssepSearch.AutoSize = false;
+ this.tssepSearch.Name = "tssepSearch";
+ this.tssepSearch.Size = new System.Drawing.Size(10, 25);
+ //
+ // AdvancedDataGridViewSearchToolBar
+ //
+ this.AllowMerge = false;
+ this.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsbtnClose,
+ this.tslblSearch,
+ this.tscmbColumns,
+ this.tstxtSearch,
+ this.tsbtnFromBegin,
+ this.tsbtnWholeWord,
+ this.tsbtnCaseSensitive,
+ this.tssepSearch,
+ this.tsbtnSearch});
+ this.MaximumSize = new System.Drawing.Size(0, 27);
+ this.MinimumSize = new System.Drawing.Size(0, 27);
+ this.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
+ this.Size = new System.Drawing.Size(0, 27);
+ this.Resize += new System.EventHandler(this.ResizeMe);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private ToolStripButton tsbtnClose;
+ private ToolStripLabel tslblSearch;
+ private ToolStripComboBox tscmbColumns;
+ private ToolStripTextBox tstxtSearch;
+ private ToolStripButton tsbtnFromBegin;
+ private ToolStripButton tsbtnCaseSensitive;
+ private ToolStripButton tsbtnSearch;
+ private ToolStripButton tsbtnWholeWord;
+ private ToolStripSeparator tssepSearch;
+
+ #endregion
+
+ #region public events
+
+ public event AdvancedDataGridViewSearchToolBarSearchEventHandler? Search;
+
+ #endregion
+
+
+ #region class properties
+
+ private DataGridViewColumnCollection? _columnsList;
+
+ private const bool BUTTON_CLOSE_ENABLED = false;
+
+ #endregion
+
+
+ #region translations
+
+ ///
+ /// Internationalization strings
+ ///
+ public static Dictionary Translations = new Dictionary()
+ {
+ { nameof(TranslationKey.ADGVSTBLabelSearch), "Search:" },
+ { nameof(TranslationKey.ADGVSTBButtonFromBegin), "From Begin" },
+ { nameof(TranslationKey.ADGVSTBButtonCaseSensitiveToolTip), "Case Sensitivity" },
+ { nameof(TranslationKey.ADGVSTBButtonSearchToolTip), "Find Next" },
+ { nameof(TranslationKey.ADGVSTBButtonCloseToolTip), "Hide" },
+ { nameof(TranslationKey.ADGVSTBButtonWholeWordToolTip), "Search only Whole Word" },
+ { nameof(TranslationKey.ADGVSTBComboBoxColumnsAll), "(All Columns)" },
+ { nameof(TranslationKey.ADGVSTBTextBoxSearchToolTip), "Value for Search" }
+ };
+
+ ///
+ /// Used to check if components translations has to be updated
+ ///
+ private Dictionary _translationsRefreshComponentTranslationsCheck = new Dictionary() { };
+
+ #endregion
+
+ #region Identity
+
+ /// Initializes a new instance of the class.
+ public KryptonAdvancedDataGridViewSearchToolBar()
+ {
+ //initialize components
+ InitializeComponent();
+
+ RefreshComponentTranslations();
+
+ //set default values
+ if (!BUTTON_CLOSE_ENABLED)
+ {
+ Items.RemoveAt(0);
+ }
+
+ tscmbColumns!.SelectedIndex = 0;
+
+ // Use Krypton
+ RenderMode = ToolStripRenderMode.ManagerRenderMode;
+ }
+
+ #endregion
+
+ #region Translations Methods
+
+ ///
+ /// Set translation dictionary
+ ///
+ ///
+ public static void SetTranslations(IDictionary? translations)
+ {
+ //set localization strings
+ if (translations != null)
+ {
+ foreach (KeyValuePair translation in translations)
+ {
+ if (Translations.ContainsKey(translation.Key))
+ {
+ Translations[translation.Key] = translation.Value;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Get translation dictionary
+ ///
+ ///
+ public static IDictionary GetTranslations()
+ {
+ return Translations;
+ }
+
+ ///
+ /// Load translations from file
+ ///
+ ///
+ ///
+ public static IDictionary LoadTranslationsFromFile(string filename)
+ {
+ IDictionary ret = new Dictionary();
+
+ if (!String.IsNullOrEmpty(filename))
+ {
+ //deserialize the file
+ try
+ {
+ string jsonText = File.ReadAllText(filename);
+#if NETFRAMEWORK
+ Dictionary translations =
+ new JavaScriptSerializer().Deserialize>(jsonText);
+#else
+ Dictionary? translations =
+ JsonSerializer.Deserialize>(jsonText);
+#endif
+ foreach (KeyValuePair translation in translations!)
+ {
+ if (!ret.ContainsKey(translation.Key) && Translations.ContainsKey(translation.Key))
+ {
+ ret.Add(translation.Key, translation.Value);
+ }
+ }
+ }
+ catch
+ {
+ // Nothing to do
+ }
+ }
+
+ //add default translations if not in files
+ foreach (KeyValuePair translation in GetTranslations())
+ {
+ if (!ret.ContainsKey(translation.Key))
+ {
+ ret.Add(translation.Key, translation.Value);
+ }
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Update components translations
+ ///
+ private void RefreshComponentTranslations()
+ {
+ tscmbColumns.BeginUpdate();
+ tscmbColumns.Items.Clear();
+ tscmbColumns.Items.AddRange([Translations[nameof(TranslationKey.ADGVSTBComboBoxColumnsAll)]]);
+ if (_columnsList != null)
+ {
+ foreach (DataGridViewColumn c in _columnsList)
+ {
+ if (c.Visible)
+ {
+ tscmbColumns.Items.Add(c.HeaderText);
+ }
+ }
+ }
+
+ tscmbColumns.SelectedIndex = 0;
+ tscmbColumns.EndUpdate();
+ tsbtnClose.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonCloseToolTip)];
+ tslblSearch.Text = Translations[nameof(TranslationKey.ADGVSTBLabelSearch)];
+ tstxtSearch.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBTextBoxSearchToolTip)];
+ tsbtnFromBegin.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonFromBegin)];
+ tsbtnCaseSensitive.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonCaseSensitiveToolTip)];
+ tsbtnSearch.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonSearchToolTip)];
+ tsbtnWholeWord.ToolTipText = Translations[nameof(TranslationKey.ADGVSTBButtonWholeWordToolTip)];
+ tstxtSearch.Text = tstxtSearch.ToolTipText;
+ }
+
+ #endregion
+
+ #region Button Events
+
+ ///
+ /// button Search Click event
+ ///
+ ///
+ ///
+ void button_search_Click(object? sender, EventArgs e)
+ {
+ if (tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText && Search != null)
+ {
+ DataGridViewColumn? c = null;
+ if (tscmbColumns.SelectedIndex > 0 && _columnsList != null && _columnsList.GetColumnCount(DataGridViewElementStates.Visible) > 0)
+ {
+ DataGridViewColumn?[] cols = _columnsList.Cast().Where(col => col.Visible).ToArray();
+
+ if (cols.Length == tscmbColumns.Items.Count - 1)
+ {
+ if (cols[tscmbColumns.SelectedIndex - 1]!.HeaderText == tscmbColumns.SelectedItem?.ToString())
+ {
+ c = cols[tscmbColumns.SelectedIndex - 1];
+ }
+ }
+ }
+
+ AdvancedDataGridViewSearchToolBarSearchEventArgs args = new AdvancedDataGridViewSearchToolBarSearchEventArgs(
+ tstxtSearch.Text,
+ c,
+ tsbtnCaseSensitive.Checked,
+ tsbtnWholeWord.Checked,
+ tsbtnFromBegin.Checked
+ );
+ Search(this, args);
+ }
+ }
+
+ ///
+ /// button Close Click event
+ ///
+ ///
+ ///
+ void button_close_Click(object? sender, EventArgs e)
+ {
+ Hide();
+ }
+
+ #endregion
+
+ #region Textbox Search Events
+
+ ///
+ /// textBox Search TextChanged event
+ ///
+ ///
+ ///
+ void textBox_search_TextChanged(object? sender, EventArgs e)
+ {
+ tsbtnSearch.Enabled = tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText;
+ }
+
+
+ ///
+ /// textBox Search Enter event
+ ///
+ ///
+ ///
+ void textBox_search_Enter(object? sender, EventArgs e)
+ {
+ if (tstxtSearch.Text == tstxtSearch.ToolTipText && tstxtSearch.ForeColor == Color.LightGray)
+ {
+ tstxtSearch.Text = "";
+ }
+ else
+ {
+ tstxtSearch.SelectAll();
+ }
+
+ tstxtSearch.ForeColor = SystemColors.WindowText;
+ }
+
+ ///
+ /// textBox Search Leave event
+ ///
+ ///
+ ///
+ void textBox_search_Leave(object? sender, EventArgs e)
+ {
+ if (tstxtSearch.Text.Trim() == "")
+ {
+ tstxtSearch.Text = tstxtSearch.ToolTipText;
+ tstxtSearch.ForeColor = Color.LightGray;
+ }
+ }
+
+
+ ///
+ /// textBox Search KeyDown event
+ ///
+ ///
+ ///
+ void textBox_search_KeyDown(object? sender, KeyEventArgs e)
+ {
+ if (tstxtSearch.TextLength > 0 && tstxtSearch.Text != tstxtSearch.ToolTipText && e.KeyData == Keys.Enter)
+ {
+ button_search_Click(tsbtnSearch, EventArgs.Empty);
+ e.SuppressKeyPress = true;
+ e.Handled = true;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Set Columns to search in
+ ///
+ ///
+ public void SetColumns(DataGridViewColumnCollection columns)
+ {
+ _columnsList = columns;
+ tscmbColumns.BeginUpdate();
+ tscmbColumns.Items.Clear();
+ tscmbColumns.Items.AddRange([Translations[nameof(TranslationKey.ADGVSTBComboBoxColumnsAll)]]);
+ if (_columnsList != null)
+ {
+ foreach (DataGridViewColumn c in _columnsList)
+ {
+ if (c.Visible)
+ {
+ tscmbColumns.Items.Add(c.HeaderText);
+ }
+ }
+ }
+
+ tscmbColumns.SelectedIndex = 0;
+ tscmbColumns.EndUpdate();
+ }
+
+ #endregion
+
+ #region Resize Events
+
+ ///
+ /// Resize event
+ ///
+ ///
+ ///
+ private void ResizeMe(object? sender, EventArgs e)
+ {
+ SuspendLayout();
+ int w1 = 150;
+ int w2 = 150;
+ int oldW = tscmbColumns.Width + tstxtSearch.Width;
+ foreach (ToolStripItem c in Items)
+ {
+ c.Overflow = ToolStripItemOverflow.Never;
+ c.Visible = true;
+ }
+
+ int width = PreferredSize.Width - oldW + w1 + w2;
+ if (Width < width)
+ {
+ tslblSearch.Visible = false;
+ GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2);
+ width = PreferredSize.Width - oldW + w1 + w2;
+
+ if (Width < width)
+ {
+ tsbtnCaseSensitive.Overflow = ToolStripItemOverflow.Always;
+ GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2);
+ width = PreferredSize.Width - oldW + w1 + w2;
+ }
+
+ if (Width < width)
+ {
+ tsbtnWholeWord.Overflow = ToolStripItemOverflow.Always;
+ GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2);
+ width = PreferredSize.Width - oldW + w1 + w2;
+ }
+
+ if (Width < width)
+ {
+ tsbtnFromBegin.Overflow = ToolStripItemOverflow.Always;
+ tssepSearch.Visible = false;
+ GetResizeBoxSize(PreferredSize.Width - oldW + w1 + w2, ref w1, ref w2);
+ width = PreferredSize.Width - oldW + w1 + w2;
+ }
+
+ if (Width < width)
+ {
+ tscmbColumns.Overflow = ToolStripItemOverflow.Always;
+ tstxtSearch.Overflow = ToolStripItemOverflow.Always;
+ w1 = 150;
+ w2 = Math.Max(Width - PreferredSize.Width - tstxtSearch.Margin.Left - tstxtSearch.Margin.Right, 75);
+ tstxtSearch.Overflow = ToolStripItemOverflow.Never;
+ width = PreferredSize.Width - tstxtSearch.Width + w2;
+ }
+ if (Width < width)
+ {
+ tsbtnSearch.Overflow = ToolStripItemOverflow.Always;
+ w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 75);
+ width = PreferredSize.Width - tstxtSearch.Width + w2;
+ }
+ if (Width < width)
+ {
+ tsbtnClose.Overflow = ToolStripItemOverflow.Always;
+ tstxtSearch.Margin = new Padding(8, 2, 8, 2);
+ w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 75);
+ width = PreferredSize.Width - tstxtSearch.Width + w2;
+ }
+
+ if (Width < width)
+ {
+ w2 = Math.Max(Width - PreferredSize.Width + tstxtSearch.Width, 20);
+ width = PreferredSize.Width - tstxtSearch.Width + w2;
+ }
+ if (width > Width)
+ {
+ tstxtSearch.Overflow = ToolStripItemOverflow.Always;
+ tstxtSearch.Margin = new Padding(0, 2, 8, 2);
+ w2 = 150;
+ }
+ }
+ else
+ {
+ GetResizeBoxSize(width, ref w1, ref w2);
+ }
+
+ if (tscmbColumns.Width != w1)
+ {
+ tscmbColumns.Width = w1;
+ }
+
+ if (tstxtSearch.Width != w2)
+ {
+ tstxtSearch.Width = w2;
+ }
+
+ ResumeLayout();
+ }
+
+ ///
+ /// Get a Resize Size for a box
+ ///
+ ///
+ ///
+ ///
+ private void GetResizeBoxSize(int width, ref int w1, ref int w2)
+ {
+ int dif = (int)Math.Round((width - Width) / 2.0, 0, MidpointRounding.AwayFromZero);
+
+ int oldW1 = w1;
+ int oldW2 = w2;
+ if (Width < width)
+ {
+ w1 = Math.Max(w1 - dif, 75);
+ w2 = Math.Max(w2 - dif, 75);
+ }
+ else
+ {
+ w1 = Math.Min(w1 - dif, 150);
+ w2 += Width - width + oldW1 - w1;
+ }
+ }
+
+ #endregion
+
+ #region Paint Events
+
+ ///
+ /// On Paint event
+ ///
+ ///
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ //check if translations are changed and update components
+ if (!(_translationsRefreshComponentTranslationsCheck == Translations || (_translationsRefreshComponentTranslationsCheck.Count == Translations.Count && !_translationsRefreshComponentTranslationsCheck.Except(Translations).Any())))
+ {
+ _translationsRefreshComponentTranslationsCheck = Translations;
+ RefreshComponentTranslations();
+ }
+
+ base.OnPaint(e);
+ }
+
+ #endregion
+}
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs
new file mode 100644
index 0000000000..e6afe620e1
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/MenuStrip.cs
@@ -0,0 +1,2537 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+using Timer = System.Windows.Forms.Timer;
+
+using static Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar;
+
+namespace Krypton.Utilities;
+
+[DesignerCategory("code")]
+internal partial class MenuStrip : ContextMenuStrip
+{
+ #region Designer Code
+
+ ///
+ /// Required designer variable.
+ ///
+ private IContainer? components;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && components != null)
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this._sortAscMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._sortDescMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._cancelSortMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._toolStripSeparator1MenuItem = new System.Windows.Forms.ToolStripSeparator();
+ this._cancelFilterMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterLastFiltersListMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._toolStripSeparator2MenuItem = new System.Windows.Forms.ToolStripSeparator();
+ this._customFilterLastFilter1MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterLastFilter2MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterLastFilter3MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterLastFilter4MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._customFilterLastFilter5MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._toolStripSeparator3MenuItem = new System.Windows.Forms.ToolStripSeparator();
+ this._checkList = new System.Windows.Forms.TreeView();
+ this._buttonFilter = new System.Windows.Forms.Button();
+ this._buttonUndofilter = new System.Windows.Forms.Button();
+ this._checkFilterListPanel = new System.Windows.Forms.Panel();
+ this._checkFilterListButtonsPanel = new System.Windows.Forms.Panel();
+ this._checkFilterListButtonsControlHost = new System.Windows.Forms.ToolStripControlHost(_checkFilterListButtonsPanel);
+ this._checkFilterListControlHost = new System.Windows.Forms.ToolStripControlHost(_checkFilterListPanel);
+ this._checkTextFilter = new System.Windows.Forms.TextBox();
+ this._checkTextFilterControlHost = new System.Windows.Forms.ToolStripControlHost(_checkTextFilter);
+ this._resizeBoxControlHost = new System.Windows.Forms.ToolStripControlHost(new System.Windows.Forms.Control());
+ this.SuspendLayout();
+ //
+ // MenuStrip
+ //
+ this.BackColor = System.Drawing.SystemColors.ControlLightLight;
+ this.AutoSize = false;
+ this.Padding = new System.Windows.Forms.Padding(0);
+ this.Margin = new System.Windows.Forms.Padding(0);
+ this.Size = new System.Drawing.Size(287, 370);
+ this.Closed += new System.Windows.Forms.ToolStripDropDownClosedEventHandler(MenuStrip_Closed);
+ this.LostFocus += new System.EventHandler(MenuStrip_LostFocus);
+ this.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ _sortAscMenuItem,
+ _sortDescMenuItem,
+ _cancelSortMenuItem,
+ _toolStripSeparator1MenuItem,
+ _cancelFilterMenuItem,
+ _customFilterLastFiltersListMenuItem,
+ _toolStripSeparator3MenuItem,
+ _checkTextFilterControlHost,
+ _checkFilterListControlHost,
+ _checkFilterListButtonsControlHost,
+ _resizeBoxControlHost});
+ //
+ // sortASCMenuItem
+ //
+ this._sortAscMenuItem.Name = "_sortAscMenuItem";
+ this._sortAscMenuItem.AutoSize = false;
+ this._sortAscMenuItem.Size = new System.Drawing.Size(Width - 1, 22);
+ this._sortAscMenuItem.Click += new System.EventHandler(SortASCMenuItem_Click);
+ this._sortAscMenuItem.MouseEnter += new System.EventHandler(SortASCMenuItem_MouseEnter);
+ this._sortAscMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ //
+ // sortDESCMenuItem
+ //
+ this._sortDescMenuItem.Name = "_sortDescMenuItem";
+ this._sortDescMenuItem.AutoSize = false;
+ this._sortDescMenuItem.Size = new System.Drawing.Size(Width - 1, 22);
+ this._sortDescMenuItem.Click += new System.EventHandler(SortDESCMenuItem_Click);
+ this._sortDescMenuItem.MouseEnter += new System.EventHandler(SortDESCMenuItem_MouseEnter);
+ this._sortDescMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ //
+ // cancelSortMenuItem
+ //
+ this._cancelSortMenuItem.Name = "_cancelSortMenuItem";
+ this._cancelSortMenuItem.Enabled = false;
+ this._cancelSortMenuItem.AutoSize = false;
+ this._cancelSortMenuItem.Size = new System.Drawing.Size(Width - 1, 22);
+ this._cancelSortMenuItem.Text = "Clear Sort";
+ this._cancelSortMenuItem.Click += new System.EventHandler(CancelSortMenuItem_Click);
+ this._cancelSortMenuItem.MouseEnter += new System.EventHandler(CancelSortMenuItem_MouseEnter);
+ //
+ // toolStripSeparator1MenuItem
+ //
+ this._toolStripSeparator1MenuItem.Name = "_toolStripSeparator1MenuItem";
+ this._toolStripSeparator1MenuItem.Size = new System.Drawing.Size(Width - 4, 6);
+ //
+ // cancelFilterMenuItem
+ //
+ this._cancelFilterMenuItem.Name = "_cancelFilterMenuItem";
+ this._cancelFilterMenuItem.Enabled = false;
+ this._cancelFilterMenuItem.AutoSize = false;
+ this._cancelFilterMenuItem.Size = new System.Drawing.Size(Width - 1, 22);
+ this._cancelFilterMenuItem.Text = "Clear Filter";
+ this._cancelFilterMenuItem.Click += new System.EventHandler(CancelFilterMenuItem_Click);
+ this._cancelFilterMenuItem.MouseEnter += new System.EventHandler(CancelFilterMenuItem_MouseEnter);
+ //
+ // toolStripMenuItem2
+ //
+ this._toolStripSeparator2MenuItem.Name = "_toolStripSeparator2MenuItem";
+ this._toolStripSeparator2MenuItem.Size = new System.Drawing.Size(149, 6);
+ this._toolStripSeparator2MenuItem.Visible = false;
+ //
+ // customFilterMenuItem
+ //
+ this._customFilterMenuItem.Name = "_customFilterMenuItem";
+ this._customFilterMenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterMenuItem.Text = "Add a Custom Filter";
+ this._customFilterMenuItem.Click += new System.EventHandler(CustomFilterMenuItem_Click);
+ //
+ // customFilterLastFilter1MenuItem
+ //
+ this._customFilterLastFilter1MenuItem.Name = "_customFilterLastFilter1MenuItem";
+ this._customFilterLastFilter1MenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterLastFilter1MenuItem.Tag = "0";
+ this._customFilterLastFilter1MenuItem.Text = null;
+ this._customFilterLastFilter1MenuItem.Visible = false;
+ this._customFilterLastFilter1MenuItem.VisibleChanged += new System.EventHandler(CustomFilterLastFilter1MenuItem_VisibleChanged);
+ this._customFilterLastFilter1MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click);
+ this._customFilterLastFilter1MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged);
+ //
+ // customFilterLastFilter2MenuItem
+ //
+ this._customFilterLastFilter2MenuItem.Name = "_customFilterLastFilter2MenuItem";
+ this._customFilterLastFilter2MenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterLastFilter2MenuItem.Tag = "1";
+ this._customFilterLastFilter2MenuItem.Text = null;
+ this._customFilterLastFilter2MenuItem.Visible = false;
+ this._customFilterLastFilter2MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click);
+ this._customFilterLastFilter2MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged);
+ //
+ // customFilterLastFilter3MenuItem
+ //
+ this._customFilterLastFilter3MenuItem.Name = "_customFilterLastFilter3MenuItem";
+ this._customFilterLastFilter3MenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterLastFilter3MenuItem.Tag = "2";
+ this._customFilterLastFilter3MenuItem.Text = null;
+ this._customFilterLastFilter3MenuItem.Visible = false;
+ this._customFilterLastFilter3MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click);
+ this._customFilterLastFilter3MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged);
+ //
+ // customFilterLastFilter3MenuItem
+ //
+ this._customFilterLastFilter4MenuItem.Name = "lastfilter4MenuItem";
+ this._customFilterLastFilter4MenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterLastFilter4MenuItem.Tag = "3";
+ this._customFilterLastFilter4MenuItem.Text = null;
+ this._customFilterLastFilter4MenuItem.Visible = false;
+ this._customFilterLastFilter4MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click);
+ this._customFilterLastFilter4MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged);
+ //
+ // customFilterLastFilter5MenuItem
+ //
+ this._customFilterLastFilter5MenuItem.Name = "_customFilterLastFilter5MenuItem";
+ this._customFilterLastFilter5MenuItem.Size = new System.Drawing.Size(152, 22);
+ this._customFilterLastFilter5MenuItem.Tag = "4";
+ this._customFilterLastFilter5MenuItem.Text = null;
+ this._customFilterLastFilter5MenuItem.Visible = false;
+ this._customFilterLastFilter5MenuItem.Click += new System.EventHandler(CustomFilterLastFilterMenuItem_Click);
+ this._customFilterLastFilter5MenuItem.TextChanged += new System.EventHandler(CustomFilterLastFilterMenuItem_TextChanged);
+ //
+ // customFilterLastFiltersListMenuItem
+ //
+ this._customFilterLastFiltersListMenuItem.Name = "_customFilterLastFiltersListMenuItem";
+ this._customFilterLastFiltersListMenuItem.AutoSize = false;
+ this._customFilterLastFiltersListMenuItem.Size = new System.Drawing.Size(Width - 1, 22);
+ this._customFilterLastFiltersListMenuItem.Image = Properties.Resources.ColumnHeader_Filtered;
+ this._customFilterLastFiltersListMenuItem.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
+ this._customFilterLastFiltersListMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ _customFilterMenuItem,
+ _toolStripSeparator2MenuItem,
+ _customFilterLastFilter1MenuItem,
+ _customFilterLastFilter2MenuItem,
+ _customFilterLastFilter3MenuItem,
+ _customFilterLastFilter4MenuItem,
+ _customFilterLastFilter5MenuItem});
+ this._customFilterLastFiltersListMenuItem.MouseEnter += new System.EventHandler(CustomFilterLastFiltersListMenuItem_MouseEnter);
+ this._customFilterLastFiltersListMenuItem.Paint += new System.Windows.Forms.PaintEventHandler(CustomFilterLastFiltersListMenuItem_Paint);
+ //
+ // toolStripMenuItem3
+ //
+ this._toolStripSeparator3MenuItem.Name = "_toolStripSeparator3MenuItem";
+ this._toolStripSeparator3MenuItem.Size = new System.Drawing.Size(Width - 4, 6);
+ //
+ // button_filter
+ //
+ this._buttonFilter.Name = "_buttonFilter";
+ this._buttonFilter.BackColor = System.Windows.Forms.Button.DefaultBackColor;
+ this._buttonFilter.UseVisualStyleBackColor = true;
+ this._buttonFilter.Margin = new System.Windows.Forms.Padding(0);
+ this._buttonFilter.Size = new System.Drawing.Size(75, 23);
+ this._buttonFilter.Text = "Filter";
+ this._buttonFilter.Click += new System.EventHandler(Button_ok_Click);
+ this._buttonFilter.Location = new System.Drawing.Point(this._checkFilterListButtonsPanel.Width - 164, 0);
+ //
+ // button_undofilter
+ //
+ this._buttonUndofilter.Name = "_buttonUndofilter";
+ this._buttonUndofilter.BackColor = System.Windows.Forms.Button.DefaultBackColor;
+ this._buttonUndofilter.UseVisualStyleBackColor = true;
+ this._buttonUndofilter.Margin = new System.Windows.Forms.Padding(0);
+ this._buttonUndofilter.Size = new System.Drawing.Size(75, 23);
+ this._buttonUndofilter.Text = "Cancel";
+ this._buttonUndofilter.Click += new System.EventHandler(Button_cancel_Click);
+ this._buttonUndofilter.Location = new System.Drawing.Point(this._checkFilterListButtonsPanel.Width - 79, 0);
+ //
+ // resizeBoxControlHost
+ //
+ this._resizeBoxControlHost.Name = "_resizeBoxControlHost";
+ this._resizeBoxControlHost.Control.Cursor = System.Windows.Forms.Cursors.SizeNWSE;
+ this._resizeBoxControlHost.AutoSize = false;
+ this._resizeBoxControlHost.Padding = new System.Windows.Forms.Padding(0);
+ this._resizeBoxControlHost.Margin = new System.Windows.Forms.Padding(Width - 45, 0, 0, 0);
+ this._resizeBoxControlHost.Size = new System.Drawing.Size(10, 10);
+ this._resizeBoxControlHost.Paint += new System.Windows.Forms.PaintEventHandler(ResizeBoxControlHost_Paint);
+ this._resizeBoxControlHost.MouseDown += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseDown);
+ this._resizeBoxControlHost.MouseUp += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseUp);
+ this._resizeBoxControlHost.MouseMove += new System.Windows.Forms.MouseEventHandler(ResizeBoxControlHost_MouseMove);
+ //
+ // checkFilterListControlHost
+ //
+ this._checkFilterListControlHost.Name = "_checkFilterListControlHost";
+ this._checkFilterListControlHost.AutoSize = false;
+ this._checkFilterListControlHost.Size = new System.Drawing.Size(Width - 35, 194);
+ this._checkFilterListControlHost.Padding = new System.Windows.Forms.Padding(0);
+ this._checkFilterListControlHost.Margin = new System.Windows.Forms.Padding(0);
+ //
+ // checkTextFilterControlHost
+ //
+ this._checkTextFilterControlHost.Name = "_checkTextFilterControlHost";
+ this._checkTextFilterControlHost.AutoSize = false;
+ this._checkTextFilterControlHost.Size = new System.Drawing.Size(Width - 35, 20);
+ this._checkTextFilterControlHost.Padding = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this._checkTextFilterControlHost.Margin = new System.Windows.Forms.Padding(0);
+ //
+ // checkFilterListButtonsControlHost
+ //
+ this._checkFilterListButtonsControlHost.Name = "_checkFilterListButtonsControlHost";
+ this._checkFilterListButtonsControlHost.AutoSize = false;
+ this._checkFilterListButtonsControlHost.Size = new System.Drawing.Size(Width - 35, 24);
+ this._checkFilterListButtonsControlHost.Padding = new System.Windows.Forms.Padding(0);
+ this._checkFilterListButtonsControlHost.Margin = new System.Windows.Forms.Padding(0);
+ //
+ // checkFilterListPanel
+ //
+ this._checkFilterListPanel.Name = "_checkFilterListPanel";
+ this._checkFilterListPanel.AutoSize = false;
+ this._checkFilterListPanel.Size = _checkFilterListControlHost.Size;
+ this._checkFilterListPanel.Padding = new System.Windows.Forms.Padding(0);
+ this._checkFilterListPanel.Margin = new System.Windows.Forms.Padding(0);
+ this._checkFilterListPanel.BackColor = BackColor;
+ this._checkFilterListPanel.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this._checkFilterListPanel.Controls.Add(_checkList);
+ //
+ // checkList
+ //
+ this._checkList.Name = "_checkList";
+ this._checkList.AutoSize = false;
+ this._checkList.Padding = new System.Windows.Forms.Padding(0);
+ this._checkList.Margin = new System.Windows.Forms.Padding(0);
+ this._checkList.Bounds = new System.Drawing.Rectangle(4, 4, this._checkFilterListPanel.Width - 8, this._checkFilterListPanel.Height - 8);
+ this._checkList.StateImageList = GetCheckListStateImages();
+ this._checkList.CheckBoxes = false;
+ this._checkList.MouseLeave += new System.EventHandler(CheckList_MouseLeave);
+ this._checkList.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(CheckList_NodeMouseClick);
+ this._checkList.KeyDown += new System.Windows.Forms.KeyEventHandler(CheckList_KeyDown);
+ this._checkList.MouseEnter += CheckList_MouseEnter;
+ this._checkList.NodeMouseDoubleClick += CheckList_NodeMouseDoubleClick;
+ //
+ // checkTextFilter
+ //
+ this._checkTextFilter.Name = "_checkTextFilter";
+ this._checkTextFilter.Padding = new System.Windows.Forms.Padding(0);
+ this._checkTextFilter.Margin = new System.Windows.Forms.Padding(0);
+ this._checkTextFilter.Size = _checkTextFilterControlHost.Size;
+ this._checkTextFilter.Dock = System.Windows.Forms.DockStyle.Fill;
+ this._checkTextFilter.TextChanged += new System.EventHandler(CheckTextFilter_TextChanged);
+ //
+ // checkFilterListButtonsPanel
+ //
+ this._checkFilterListButtonsPanel.Name = "_checkFilterListButtonsPanel";
+ this._checkFilterListButtonsPanel.AutoSize = false;
+ this._checkFilterListButtonsPanel.Size = _checkFilterListButtonsControlHost.Size;
+ this._checkFilterListButtonsPanel.Padding = new System.Windows.Forms.Padding(0);
+ this._checkFilterListButtonsPanel.Margin = new System.Windows.Forms.Padding(0);
+ this._checkFilterListButtonsPanel.BackColor = BackColor;
+ this._checkFilterListButtonsPanel.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this._checkFilterListButtonsPanel.Controls.AddRange(new System.Windows.Forms.Control[] {
+ _buttonFilter,
+ _buttonUndofilter
+ });
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private ToolStripMenuItem _sortAscMenuItem;
+ private ToolStripMenuItem _sortDescMenuItem;
+ private ToolStripMenuItem _cancelSortMenuItem;
+ private ToolStripSeparator _toolStripSeparator1MenuItem;
+ private ToolStripSeparator _toolStripSeparator2MenuItem;
+ private ToolStripSeparator _toolStripSeparator3MenuItem;
+ private ToolStripMenuItem _cancelFilterMenuItem;
+ private ToolStripMenuItem _customFilterLastFiltersListMenuItem;
+ private ToolStripMenuItem _customFilterMenuItem;
+ private ToolStripMenuItem _customFilterLastFilter1MenuItem;
+ private ToolStripMenuItem _customFilterLastFilter2MenuItem;
+ private ToolStripMenuItem _customFilterLastFilter3MenuItem;
+ private ToolStripMenuItem _customFilterLastFilter4MenuItem;
+ private ToolStripMenuItem _customFilterLastFilter5MenuItem;
+ private TreeView _checkList;
+ private Button _buttonFilter;
+ private Button _buttonUndofilter;
+ private ToolStripControlHost _checkFilterListControlHost;
+ private ToolStripControlHost _checkFilterListButtonsControlHost;
+ private ToolStripControlHost _resizeBoxControlHost;
+ private Panel _checkFilterListPanel;
+ private Panel _checkFilterListButtonsPanel;
+ private TextBox _checkTextFilter;
+ private ToolStripControlHost _checkTextFilterControlHost;
+
+ #endregion
+
+ #region public enum
+
+ ///
+ /// MenuStrip Filter type
+ ///
+ public enum FilterType : byte
+ {
+ None = 0,
+ Custom = 1,
+ CheckList = 2,
+ Loaded = 3
+ }
+
+
+ ///
+ /// MenuStrip Sort type
+ ///
+ public enum SortType : byte
+ {
+ None = 0,
+ Asc = 1,
+ Desc = 2
+ }
+
+ #endregion
+
+
+ #region public constants
+
+ ///
+ /// Default checklist filter node behaviour
+ ///
+ public const bool DefaultCheckTextFilterRemoveNodesOnSearch = true;
+
+ ///
+ /// Default max filter checklist max nodes
+ ///
+ public const int DefaultMaxChecklistNodes = 10000;
+
+ ///
+ /// Default number of nodes to enable the TextChanged delay on text filter
+ ///
+ public const int DefaultTextFilterTextChangedDelayNodes = 1000;
+
+ ///
+ /// Number of nodes to disable the text filter TextChanged delay
+ ///
+ public const int TextFilterTextChangedDelayNodesDisabled = -1;
+
+ ///
+ /// Default delay milliseconds for TextChanged delay on text filter
+ ///
+ public const int DefaultTextFilterTextChangedDelayMs = 300;
+
+ #endregion
+
+
+ #region class properties
+
+ private FilterType _activeFilterType = FilterType.None;
+ private SortType _activeSortType = SortType.None;
+ private TreeNodeItemSelector?[] _loadedNodes = [];
+ private TreeNodeItemSelector?[] _startingNodes = [];
+ private TreeNodeItemSelector?[] _removedNodes = [];
+ private TreeNodeItemSelector?[] _removedSessionNodes = [];
+ private string? _sortString;
+ private string? _filterString;
+ private static readonly Point _resizeStartPoint = new Point(1, 1);
+ private Point _resizeEndPoint = new Point(-1, -1);
+ private bool _checkTextFilterChangedEnabled = true;
+ private bool _checkTextFilterRemoveNodesOnSearch = DefaultCheckTextFilterRemoveNodesOnSearch;
+ private int _maxChecklistNodes = DefaultMaxChecklistNodes;
+ private bool _filterClick;
+ private Timer? _textFilterTextChangedTimer;
+ private int _textFilterTextChangedDelayNodes = DefaultTextFilterTextChangedDelayNodes;
+ private int _textFilterTextChangedDelayMs = DefaultTextFilterTextChangedDelayMs;
+
+ #endregion
+
+
+ #region Identity
+
+ ///
+ /// MenuStrip constructor
+ ///
+ ///
+ public MenuStrip(Type dataType)
+ : base()
+ {
+ //initialize components
+ InitializeComponent();
+
+ //set component translations
+ _cancelSortMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewClearSort)];
+ _cancelFilterMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewClearFilter)];
+ _customFilterMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewAddCustomFilter)];
+ _buttonFilter!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonFilter)];
+ _buttonUndofilter!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonUndoFilter)];
+
+ //set type
+ DataType = dataType;
+
+ //set components values
+ if (DataType == typeof(DateTime) || DataType == typeof(TimeSpan))
+ {
+ _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)];
+ _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeAscending)];
+ _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortDateTimeDescending)];
+ _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCnum;
+ _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCnum;
+ }
+ else if (DataType == typeof(bool))
+ {
+ _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)];
+ _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolAscending)];
+ _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortBoolDescending)];
+ _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCbool;
+ _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCbool;
+ }
+ else if (DataType == typeof(Int32) || DataType == typeof(Int64) || DataType == typeof(Int16) ||
+ DataType == typeof(UInt32) || DataType == typeof(UInt64) || DataType == typeof(UInt16) ||
+ DataType == typeof(Byte) || DataType == typeof(SByte) || DataType == typeof(Decimal) ||
+ DataType == typeof(Single) || DataType == typeof(Double))
+ {
+ _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)];
+ _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumAscending)];
+ _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortNumDescending)];
+ _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCnum;
+ _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCnum;
+ }
+ else
+ {
+ _customFilterLastFiltersListMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewCustomFilter)];
+ _sortAscMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextAscending)];
+ _sortDescMenuItem!.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewSortTextDescending)];
+ _sortAscMenuItem.Image = Properties.Resources.MenuStrip_OrderASCtxt;
+ _sortDescMenuItem.Image = Properties.Resources.MenuStrip_OrderDESCtxt;
+ }
+
+ //set check filter textbox
+ if (DataType == typeof(DateTime) || DataType == typeof(TimeSpan) || DataType == typeof(bool))
+ {
+ _checkTextFilter!.Enabled = false;
+ }
+
+ //set default NOT IN logic
+ IsFilterNotinLogicEnabled = false;
+
+ //sent enablers default
+ IsSortEnabled = true;
+ IsFilterEnabled = true;
+ IsFilterChecklistEnabled = true;
+ IsFilterDateAndTimeEnabled = true;
+
+ //set default components
+ _customFilterLastFiltersListMenuItem.Enabled = DataType != typeof(bool);
+ _customFilterLastFiltersListMenuItem.Checked = ActiveFilterType == FilterType.Custom;
+
+ //resize before hitting ResizeBox so the grip works correctly
+ float scalingFactor = GetScalingFactor();
+ MinimumSize = new Size(Scale(PreferredSize.Width, scalingFactor), Scale(PreferredSize.Height, scalingFactor));
+ //once the size is set resize the ones that won't change
+ _resizeBoxControlHost!.Height = Scale(_resizeBoxControlHost.Height, scalingFactor);
+ _resizeBoxControlHost.Width = Scale(_resizeBoxControlHost.Width, scalingFactor);
+ _toolStripSeparator1MenuItem!.Height = Scale(_toolStripSeparator1MenuItem.Height, scalingFactor);
+ _toolStripSeparator2MenuItem!.Height = Scale(_toolStripSeparator2MenuItem.Height, scalingFactor);
+ _toolStripSeparator3MenuItem!.Height = Scale(_toolStripSeparator3MenuItem.Height, scalingFactor);
+ _sortAscMenuItem.Height = Scale(_sortAscMenuItem.Height, scalingFactor);
+ _sortDescMenuItem.Height = Scale(_sortDescMenuItem.Height, scalingFactor);
+ _cancelSortMenuItem.Height = Scale(_cancelSortMenuItem.Height, scalingFactor);
+ _cancelFilterMenuItem.Height = Scale(_cancelFilterMenuItem.Height, scalingFactor);
+ _customFilterMenuItem.Height = Scale(_customFilterMenuItem.Height, scalingFactor);
+ _customFilterLastFiltersListMenuItem.Height = Scale(_customFilterLastFiltersListMenuItem.Height, scalingFactor);
+ _checkTextFilterControlHost!.Height = Scale(_checkTextFilterControlHost.Height, scalingFactor);
+ _buttonFilter.Width = Scale(_buttonFilter.Width, scalingFactor);
+ _buttonFilter.Height = Scale(_buttonFilter.Height, scalingFactor);
+ _buttonUndofilter.Width = Scale(_buttonUndofilter.Width, scalingFactor);
+ _buttonUndofilter.Height = Scale(_buttonUndofilter.Height, scalingFactor);
+ //resize
+ ResizeBox(MinimumSize.Width, MinimumSize.Height);
+
+ _textFilterTextChangedTimer = new Timer();
+ _textFilterTextChangedTimer.Interval = _textFilterTextChangedDelayMs;
+ _textFilterTextChangedTimer.Tick += new EventHandler(CheckTextFilterTextChangedTimer_Tick);
+
+ RenderMode = ToolStripRenderMode.ManagerRenderMode;
+ }
+
+ ///
+ /// Closed event
+ ///
+ ///
+ ///
+ private void MenuStrip_Closed(object? sender, EventArgs e)
+ {
+ ResizeClean();
+
+ if (_checkTextFilterRemoveNodesOnSearch && !_filterClick)
+ {
+ _loadedNodes = DuplicateNodes(_startingNodes);
+ }
+
+ _startingNodes = [];
+
+ _checkTextFilterChangedEnabled = false;
+ _checkTextFilter.Text = "";
+ _checkTextFilterChangedEnabled = true;
+ }
+
+ ///
+ /// LostFocus event
+ ///
+ ///
+ ///
+ private void MenuStrip_LostFocus(object? sender, EventArgs e)
+ {
+ if (!ContainsFocus)
+ {
+ Close();
+ }
+ }
+
+ ///
+ /// Control removed event
+ ///
+ ///
+ protected override void OnControlRemoved(ControlEventArgs e)
+ {
+ _loadedNodes = [];
+ _startingNodes = [];
+ _removedNodes = [];
+ _removedSessionNodes = [];
+ _textFilterTextChangedTimer?.Stop();
+
+ base.OnControlRemoved(e);
+ }
+
+ ///
+ /// Get all images for checkList
+ ///
+ ///
+ private static ImageList GetCheckListStateImages()
+ {
+ ImageList images = new ImageList();
+ Bitmap unCheckImg = new Bitmap(16, 16);
+ Bitmap checkImg = new Bitmap(16, 16);
+ Bitmap mixedImg = new Bitmap(16, 16);
+
+ using (Bitmap img = new Bitmap(16, 16))
+ {
+ using (Graphics g = Graphics.FromImage(img))
+ {
+ CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.UncheckedNormal);
+ unCheckImg = (Bitmap)img.Clone();
+ CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.CheckedNormal);
+ checkImg = (Bitmap)img.Clone();
+ CheckBoxRenderer.DrawCheckBox(g, new Point(0, 1), CheckBoxState.MixedNormal);
+ mixedImg = (Bitmap)img.Clone();
+ }
+ }
+
+ images.Images.Add("uncheck", unCheckImg);
+ images.Images.Add("check", checkImg);
+ images.Images.Add("mixed", mixedImg);
+
+ return images;
+ }
+
+ #endregion
+
+
+ #region public events
+
+ ///
+ /// The current Sorting in changed
+ ///
+ public event EventHandler? SortChanged;
+
+ ///
+ /// The current Filter is changed
+ ///
+ public event EventHandler? FilterChanged;
+
+ #endregion
+
+
+ #region public getter and setters
+
+ ///
+ /// Set the max checklist nodes
+ ///
+ [DefaultValue(DefaultMaxChecklistNodes)]
+ public int MaxChecklistNodes
+ {
+ get => _maxChecklistNodes;
+ set => _maxChecklistNodes = value;
+ }
+
+ ///
+ /// Get the current MenuStripSortType type
+ ///
+ public SortType ActiveSortType => _activeSortType;
+
+ ///
+ /// Get the current MenuStripFilterType type
+ ///
+ public FilterType ActiveFilterType => _activeFilterType;
+
+ ///
+ /// Get the DataType for the MenuStrip Filter
+ ///
+ public Type DataType { get; private set; }
+
+ ///
+ /// Get or Set the Filter Sort enabled
+ ///
+ [DefaultValue(false)]
+ public bool IsSortEnabled { get; set; }
+
+ ///
+ /// Get or Set the Filter enabled
+ ///
+ [DefaultValue(false)]
+ public bool IsFilterEnabled { get; set; }
+
+ ///
+ /// Get or Set the Filter Checklist enabled
+ ///
+ [DefaultValue(false)]
+ public bool IsFilterChecklistEnabled { get; set; }
+
+ ///
+ /// Get or Set the Filter Custom enabled
+ ///
+ [DefaultValue(false)]
+ public bool IsFilterCustomEnabled { get; set; }
+
+ ///
+ /// Get or Set the Filter DateAndTime enabled
+ ///
+ [DefaultValue(false)]
+ public bool IsFilterDateAndTimeEnabled { get; set; }
+
+ ///
+ /// Get or Set the NOT IN logic for Filter
+ ///
+ [DefaultValue(false)]
+ public bool IsFilterNotinLogicEnabled { get; set; }
+
+ ///
+ /// Set the text filter search nodes behaviour
+ ///
+ [DefaultValue(DefaultCheckTextFilterRemoveNodesOnSearch)]
+ public bool DoesTextFilterRemoveNodesOnSearch
+ {
+ get => _checkTextFilterRemoveNodesOnSearch;
+ set => _checkTextFilterRemoveNodesOnSearch = value;
+ }
+
+ ///
+ /// Number of nodes to enable the TextChanged delay on text filter
+ ///
+ [DefaultValue(DefaultTextFilterTextChangedDelayNodes)]
+ public int TextFilterTextChangedDelayNodes
+ {
+ get => _textFilterTextChangedDelayNodes;
+ set => _textFilterTextChangedDelayNodes = value;
+ }
+
+ ///
+ /// Delay milliseconds for TextChanged delay on text filter
+ ///
+ [DefaultValue(DefaultTextFilterTextChangedDelayMs)]
+ public int TextFilterTextChangedDelayMs
+ {
+ get => _textFilterTextChangedDelayMs;
+ set => _textFilterTextChangedDelayMs = value;
+ }
+
+ #endregion
+
+
+ #region public enablers
+
+ ///
+ /// Enabled or disable Sorting capabilities
+ ///
+ ///
+ public void SetSortEnabled(bool enabled)
+ {
+ IsSortEnabled = enabled;
+
+ _sortAscMenuItem.Enabled = enabled;
+ _sortDescMenuItem.Enabled = enabled;
+ _cancelSortMenuItem.Enabled = enabled;
+ }
+
+ ///
+ /// Enable or disable Filter capabilities
+ ///
+ ///
+ public void SetFilterEnabled(bool enabled)
+ {
+ IsFilterEnabled = enabled;
+
+ _cancelFilterMenuItem.Enabled = enabled;
+ _customFilterLastFiltersListMenuItem.Enabled = enabled && DataType != typeof(bool);
+ _buttonFilter.Enabled = enabled;
+ _buttonUndofilter.Enabled = enabled;
+ _checkList.Enabled = enabled;
+ _checkTextFilter.Enabled = enabled;
+ }
+
+ ///
+ /// Enable or disable Filter checklist capabilities
+ ///
+ ///
+ public void SetFilterChecklistEnabled(bool enabled)
+ {
+ if (!IsFilterEnabled)
+ {
+ enabled = false;
+ }
+
+ IsFilterChecklistEnabled = enabled;
+ _checkList.Enabled = enabled;
+ _checkTextFilter.ReadOnly = !enabled;
+
+ if (!IsFilterChecklistEnabled)
+ {
+ ChecklistClearNodes();
+ TreeNodeItemSelector disabledNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFilterChecklistDisable)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll);
+ disabledNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold);
+ ChecklistAddNode(disabledNode);
+ ChecklistReloadNodes();
+ }
+ }
+
+ ///
+ /// Enable or disable Filter custom capabilities
+ ///
+ ///
+ public void SetFilterCustomEnabled(bool enabled)
+ {
+ if (!IsFilterEnabled)
+ {
+ enabled = false;
+ }
+
+ IsFilterCustomEnabled = enabled;
+ _customFilterMenuItem.Enabled = enabled;
+ _customFilterLastFiltersListMenuItem.Enabled = enabled;
+
+ if (!IsFilterCustomEnabled)
+ {
+ UnCheckCustomFilters();
+ }
+ }
+
+ ///
+ /// Disable text filter TextChanged delay
+ ///
+ public void SetTextFilterTextChangedDelayNodesDisabled()
+ {
+ _textFilterTextChangedDelayNodes = TextFilterTextChangedDelayNodesDisabled;
+ }
+
+ #endregion
+
+
+ #region preset loader
+
+ public void SetLoadedMode(bool enabled)
+ {
+ _customFilterMenuItem.Enabled = !enabled;
+ _cancelFilterMenuItem.Enabled = enabled;
+ if (enabled)
+ {
+ _activeFilterType = FilterType.Loaded;
+ _sortString = null;
+ _filterString = null;
+ _customFilterLastFiltersListMenuItem.Checked = false;
+ for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count - 1; i++)
+ {
+ ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false;
+ }
+
+ ChecklistClearNodes();
+ TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Indeterminate, TreeNodeItemSelector.CustomNodeType.SelectAll);
+ allNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold);
+ ChecklistAddNode(allNode);
+ ChecklistReloadNodes();
+
+ SetSortEnabled(false);
+ SetFilterEnabled(false);
+ }
+ else
+ {
+ _activeFilterType = FilterType.None;
+
+ SetSortEnabled(true);
+ SetFilterEnabled(true);
+ }
+ }
+
+ #endregion
+
+
+ #region public show methods
+
+ ///
+ /// Show the menuStrip
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void Show(Control control, int x, int y, IEnumerable vals)
+ {
+ _removedNodes = [];
+ _removedSessionNodes = [];
+
+ //add nodes
+ BuildNodes(vals);
+ //set the starting nodes
+ _startingNodes = DuplicateNodes(_loadedNodes);
+
+ if (_activeFilterType == FilterType.Custom)
+ {
+ SetNodesCheckState(_loadedNodes, false);
+ }
+
+ base.Show(control, x, y);
+
+ _filterClick = false;
+
+ _checkTextFilterChangedEnabled = false;
+ _checkTextFilter.Text = "";
+ _checkTextFilterChangedEnabled = true;
+ }
+
+ ///
+ /// Show the menuStrip
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void Show(Control control, int x, int y, bool restoreFilter)
+ {
+ _checkTextFilterChangedEnabled = false;
+ _checkTextFilter.Text = "";
+ _checkTextFilterChangedEnabled = true;
+ if (restoreFilter || _checkTextFilterRemoveNodesOnSearch)
+ {
+ //reset the starting nodes
+ _startingNodes = DuplicateNodes(_loadedNodes);
+ }
+ //reset removed nodes
+ if (_checkTextFilterRemoveNodesOnSearch)
+ {
+ _removedNodes = _loadedNodes.Where(n => n!.CheckState == CheckState.Unchecked && n.NodeType == TreeNodeItemSelector.CustomNodeType.Default).ToArray();
+ _removedSessionNodes = _removedNodes;
+ }
+
+ ChecklistReloadNodes();
+
+ base.Show(control, x, y);
+
+ _filterClick = false;
+ }
+
+ ///
+ /// Get values used for Show method
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable GetValuesForFilter(DataGridView grid, string columnName)
+ {
+ var vals =
+ from DataGridViewRow nulls in grid.Rows
+ select nulls.Cells[columnName];
+
+ return vals;
+ }
+
+ #endregion
+
+
+ #region public sort methods
+
+ ///
+ /// Sort ASC
+ ///
+ public void SortAsc()
+ {
+ SortASCMenuItem_Click(this, null);
+ }
+
+ ///
+ /// Sort DESC
+ ///
+ public void SortDesc()
+ {
+ SortDESCMenuItem_Click(this, null);
+ }
+
+ ///
+ /// Get the Sorting String
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string? SortString
+ {
+ get => !String.IsNullOrEmpty(_sortString) ? _sortString : "";
+ private set
+ {
+ _cancelSortMenuItem.Enabled = value is { Length: > 0 };
+ _sortString = value;
+ }
+ }
+
+ ///
+ /// Clean the Sorting
+ ///
+ public void CleanSort()
+ {
+ _sortAscMenuItem.Checked = false;
+ _sortDescMenuItem.Checked = false;
+ _activeSortType = SortType.None;
+ SortString = null;
+ }
+
+ #endregion
+
+
+ #region public filter methods
+
+ ///
+ /// Get the Filter string
+ ///
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string? FilterString
+ {
+ get => !String.IsNullOrEmpty(_filterString) ? _filterString : "";
+ private set
+ {
+ _cancelFilterMenuItem.Enabled = value is { Length: > 0 };
+ _filterString = value;
+ }
+ }
+
+ ///
+ /// Clean the Filter
+ ///
+ public void CleanFilter()
+ {
+ if (_checkTextFilterRemoveNodesOnSearch)
+ {
+ _removedNodes = [];
+ _removedSessionNodes = [];
+ }
+
+ for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count - 1; i++)
+ {
+ ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false;
+ }
+ _activeFilterType = FilterType.None;
+ SetNodesCheckState(_loadedNodes, true);
+ FilterString = null;
+ _customFilterLastFiltersListMenuItem.Checked = false;
+ _buttonFilter.Enabled = true;
+ }
+
+ ///
+ /// Set the text filter on checklist remove node mode
+ ///
+ ///
+ public void SetChecklistTextFilterRemoveNodesOnSearchMode(bool enabled)
+ {
+ if (_checkTextFilterRemoveNodesOnSearch != enabled)
+ {
+ _checkTextFilterRemoveNodesOnSearch = enabled;
+ CleanFilter();
+ }
+ }
+
+ #endregion
+
+
+ #region checklist filter methods
+
+ ///
+ /// Clear checklist loaded nodes
+ ///
+ private void ChecklistClearNodes()
+ {
+ _loadedNodes = [];
+ }
+
+ ///
+ /// Add a node to checklist nodes
+ ///
+ ///
+ private void ChecklistAddNode(TreeNodeItemSelector node)
+ {
+ _loadedNodes = _loadedNodes.Concat([node]).ToArray();
+ }
+
+ ///
+ /// Load checklist nodes
+ ///
+ private void ChecklistReloadNodes()
+ {
+ _checkList.BeginUpdate();
+ _checkList.Nodes.Clear();
+ int nodeCount = 0;
+ foreach (TreeNodeItemSelector? node in _loadedNodes)
+ {
+ if (node!.NodeType == TreeNodeItemSelector.CustomNodeType.Default)
+ {
+ if (_maxChecklistNodes == 0)
+ {
+ if (!_removedNodes.Contains(node))
+ {
+ _checkList.Nodes.Add(node);
+ }
+ }
+ else
+ {
+ if (nodeCount < _maxChecklistNodes && !_removedNodes.Contains(node))
+ {
+ _checkList.Nodes.Add(node);
+ }
+ else if (nodeCount == _maxChecklistNodes)
+ {
+ _checkList.Nodes.Add("...");
+ }
+
+ if (!_removedNodes.Contains(node) || nodeCount == _maxChecklistNodes)
+ {
+ nodeCount++;
+ }
+ }
+ }
+ else
+ {
+ _checkList.Nodes.Add(node);
+ }
+
+ }
+ _checkList.EndUpdate();
+ }
+
+ ///
+ /// Get checklist nodes
+ ///
+ ///
+ private TreeNodeCollection ChecklistNodes() => _checkList.Nodes;
+
+ ///
+ /// Set the Filter String using checkList selected Nodes
+ ///
+ private void SetCheckListFilter()
+ {
+ UnCheckCustomFilters();
+
+ TreeNodeItemSelector? selectAllNode = GetSelectAllNode();
+ _customFilterLastFiltersListMenuItem.Checked = false;
+
+ if (selectAllNode is { Checked: true } && string.IsNullOrEmpty(_checkTextFilter.Text))
+ {
+ CancelFilterMenuItem_Click(null, EventArgs.Empty);
+ }
+ else
+ {
+ string? oldFilter = FilterString;
+ FilterString = "";
+ _activeFilterType = FilterType.CheckList;
+
+ if (_loadedNodes.Length > 1)
+ {
+ selectAllNode = GetSelectEmptyNode();
+ if (selectAllNode is { Checked: true })
+ {
+ FilterString = "[{0}] IS NULL";
+ }
+
+ if (_loadedNodes.Length > 2 || selectAllNode == null)
+ {
+ string filter = BuildNodesFilterString(
+ IsFilterNotinLogicEnabled && DataType != typeof(DateTime) && DataType != typeof(TimeSpan) && DataType != typeof(bool) ?
+ _loadedNodes.AsParallel().Cast().Where(
+ n => n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectAll
+ && n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectEmpty
+ && n.CheckState == CheckState.Unchecked
+ ) :
+ _loadedNodes.AsParallel().Cast().Where(
+ n => n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectAll
+ && n.NodeType != TreeNodeItemSelector.CustomNodeType.SelectEmpty
+ && n.CheckState != CheckState.Unchecked
+ )
+ );
+
+ if (filter.Length > 0)
+ {
+ if (FilterString.Length > 0)
+ {
+ FilterString += " OR ";
+ }
+
+ if (DataType == typeof(bool))
+ {
+ FilterString += $"[{{0}}] ={filter}";
+ }
+ else if (DataType == typeof(int) || DataType == typeof(long) || DataType == typeof(short) ||
+ DataType == typeof(uint) || DataType == typeof(ulong) || DataType == typeof(ushort) ||
+ DataType == typeof(decimal) ||
+ DataType == typeof(byte) || DataType == typeof(sbyte) || DataType == typeof(string))
+ {
+ if (IsFilterNotinLogicEnabled)
+ {
+ FilterString += $"[{{0}}] NOT IN ({filter})";
+ }
+ else
+ {
+ FilterString += $"[{{0}}] IN ({filter})";
+ }
+ }
+ else if (DataType == typeof(Bitmap))
+ { }
+ else
+ {
+ if (IsFilterNotinLogicEnabled)
+ {
+ FilterString += $"Convert([{{0}}],System.String) NOT IN ({filter})";
+ }
+ else
+ {
+ FilterString += $"Convert([{{0}}],System.String) IN ({filter})";
+ }
+ }
+ }
+ }
+ }
+
+ if (oldFilter != FilterString && FilterChanged != null)
+ {
+ FilterChanged(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ ///
+ /// Build a Filter string based on selected Nodes
+ ///
+ ///
+ ///
+ private string BuildNodesFilterString(IEnumerable? nodes)
+ {
+ StringBuilder sb = new StringBuilder("");
+
+ string appx = ", ";
+
+ var treeNodeItemSelectors = nodes as TreeNodeItemSelector[] ?? nodes?.ToArray();
+ if (nodes != null && treeNodeItemSelectors!.Any())
+ {
+ if (DataType == typeof(DateTime))
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ if (n.Checked && !n.Nodes.AsParallel().Cast()
+ .Any(sn => sn.CheckState != CheckState.Unchecked))
+ {
+ DateTime dt = (DateTime)n.Value!;
+ sb.Append(
+ $"'{Convert.ToString(IsFilterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'{appx}");
+ }
+ else if (n.CheckState != CheckState.Unchecked && n.Nodes.Count > 0)
+ {
+ string subnode = BuildNodesFilterString(n.Nodes.AsParallel().Cast()
+ .Where(sn => sn.CheckState != CheckState.Unchecked));
+ if (subnode.Length > 0)
+ {
+ sb.Append(subnode + appx);
+ }
+ }
+ }
+ }
+ }
+ else if (DataType == typeof(TimeSpan))
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ if (n.Checked && !n.Nodes.AsParallel().Cast()
+ .Any(sn => sn.CheckState != CheckState.Unchecked))
+ {
+ TimeSpan ts = (TimeSpan)n.Value!;
+ sb.Append(
+ $"'P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}'{appx}");
+ }
+ else if (n.CheckState != CheckState.Unchecked && n.Nodes.Count > 0)
+ {
+ string subnode = BuildNodesFilterString(n.Nodes.AsParallel().Cast()
+ .Where(sn => sn.CheckState != CheckState.Unchecked));
+ if (subnode.Length > 0)
+ {
+ sb.Append(subnode + appx);
+ }
+ }
+ }
+ }
+ }
+ else if (DataType == typeof(bool))
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ sb.Append(n.Value);
+ break;
+ }
+ }
+ }
+ else if (DataType == typeof(int) || DataType == typeof(long) || DataType == typeof(short) ||
+ DataType == typeof(uint) || DataType == typeof(ulong) || DataType == typeof(ushort) ||
+ DataType == typeof(byte) || DataType == typeof(sbyte))
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ sb.Append(n.Value + appx);
+ }
+ }
+ }
+ else if (DataType == typeof(float) || DataType == typeof(double) || DataType == typeof(decimal))
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ sb.Append((n.Value?.ToString() ?? string.Empty).Replace(",", ".") + appx);
+ }
+ }
+ }
+ else if (DataType == typeof(Bitmap))
+ { }
+ else
+ {
+ if (treeNodeItemSelectors != null)
+ {
+ foreach (TreeNodeItemSelector n in treeNodeItemSelectors)
+ {
+ sb.Append($"'{FormatFilterString(n.Value?.ToString()!)}'{appx}");
+ }
+ }
+ }
+ }
+
+ if (sb.Length > appx.Length && DataType != typeof(bool))
+ {
+ sb.Remove(sb.Length - appx.Length, appx.Length);
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// Format a text Filter string
+ ///
+ ///
+ ///
+ private static string FormatFilterString(string text)
+ {
+ return text.Replace("'", "''");
+ }
+
+ ///
+ /// Add nodes to checkList
+ ///
+ ///
+ private void BuildNodes(IEnumerable? vals)
+ {
+ if (!IsFilterChecklistEnabled)
+ {
+ return;
+ }
+
+ ChecklistClearNodes();
+
+ if (vals != null)
+ {
+ //add select all node
+ TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll);
+ allNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold);
+ ChecklistAddNode(allNode);
+
+ if (vals.Any())
+ {
+ var noNulls = vals.Where(c => c.Value != null && c.Value != DBNull.Value);
+
+ //add select empty node
+ IEnumerable dataGridViewCells = noNulls as DataGridViewCell[] ?? noNulls.ToArray();
+ if (vals.Count() != dataGridViewCells.Count())
+ {
+ TreeNodeItemSelector nullNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectEmpty);
+ nullNode.NodeFont = new Font(_checkList.Font, FontStyle.Bold);
+ ChecklistAddNode(nullNode);
+ }
+
+ //add datetime nodes
+ if (DataType == typeof(DateTime))
+ {
+ var years =
+ from year in dataGridViewCells
+ group year by ((DateTime)year.Value!).Year into cy
+ orderby cy.Key ascending
+ select cy;
+
+ foreach (var year in years)
+ {
+ TreeNodeItemSelector yearNode = TreeNodeItemSelector.CreateNode(year.Key.ToString(), year.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.DateTimeNode);
+ ChecklistAddNode(yearNode);
+
+ var months =
+ from month in year
+ group month by ((DateTime)month.Value!).Month into cm
+ orderby cm.Key ascending
+ select cm;
+
+ foreach (var month in months)
+ {
+ TreeNodeItemSelector? monthNode = yearNode.CreateChildNode(CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month.Key), month.Key);
+
+ var days =
+ from day in month
+ group day by ((DateTime)day.Value!).Day into cd
+ orderby cd.Key ascending
+ select cd;
+
+ foreach (var day in days)
+ {
+ TreeNodeItemSelector? daysNode;
+
+ if (!IsFilterDateAndTimeEnabled)
+ {
+ daysNode = monthNode?.CreateChildNode(day.Key.ToString("D2"), day.First().Value);
+ }
+ else
+ {
+ daysNode = monthNode?.CreateChildNode(day.Key.ToString("D2"), day.Key);
+
+ var hours =
+ from hour in day
+ group hour by ((DateTime)hour.Value!).Hour into ch
+ orderby ch.Key ascending
+ select ch;
+
+ foreach (var hour in hours)
+ {
+ TreeNodeItemSelector? hoursNode = daysNode?.CreateChildNode(
+ $"{hour.Key:D2} h", hour.Key);
+
+ var mins =
+ from min in hour
+ group min by ((DateTime)min.Value!).Minute into cmin
+ orderby cmin.Key ascending
+ select cmin;
+
+ foreach (var min in mins)
+ {
+ TreeNodeItemSelector? minsNode = hoursNode?.CreateChildNode(
+ $"{min.Key:D2} m", min.Key);
+
+ var secs =
+ from sec in min
+ group sec by ((DateTime)sec.Value!).Second into cs
+ orderby cs.Key ascending
+ select cs;
+
+ foreach (var sec in secs)
+ {
+ TreeNodeItemSelector? secsNode = minsNode?.CreateChildNode(
+ $"{sec.Key:D2} s", sec.First().Value);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //add timespan nodes
+ else if (DataType == typeof(TimeSpan))
+ {
+ var days =
+ from day in dataGridViewCells
+ group day by ((TimeSpan)day.Value!).Days into cd
+ orderby cd.Key ascending
+ select cd;
+
+ foreach (var day in days)
+ {
+ TreeNodeItemSelector daysNode = TreeNodeItemSelector.CreateNode(day.Key.ToString("D2"), day.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.DateTimeNode);
+ ChecklistAddNode(daysNode);
+
+ var hours =
+ from hour in day
+ group hour by ((TimeSpan)hour.Value!).Hours into ch
+ orderby ch.Key ascending
+ select ch;
+
+ foreach (var hour in hours)
+ {
+ TreeNodeItemSelector? hoursNode = daysNode.CreateChildNode($"{hour.Key:D2} h", hour.Key);
+
+ var mins =
+ from min in hour
+ group min by ((TimeSpan)min.Value!).Minutes into cmin
+ orderby cmin.Key ascending
+ select cmin;
+
+ foreach (var min in mins)
+ {
+ TreeNodeItemSelector? minsNode = hoursNode?.CreateChildNode($"{min.Key:D2} m", min.Key);
+
+ var secs =
+ from sec in min
+ group sec by ((TimeSpan)sec.Value!).Seconds into cs
+ orderby cs.Key ascending
+ select cs;
+
+ foreach (var sec in secs)
+ {
+ TreeNodeItemSelector? secsNode = minsNode?.CreateChildNode($"{sec.Key:D2} s", sec.First().Value);
+ }
+ }
+ }
+ }
+ }
+
+ //add boolean nodes
+ else if (DataType == typeof(bool))
+ {
+ var values = dataGridViewCells.Where(c => c.Value is true);
+
+ var gridViewCells = values as DataGridViewCell[] ?? values.ToArray();
+ if (gridViewCells.Count() != dataGridViewCells.Count())
+ {
+ TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectFalse)], false, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default);
+ ChecklistAddNode(node);
+ }
+
+ if (gridViewCells.Any())
+ {
+ TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectTrue)], true, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default);
+ ChecklistAddNode(node);
+ }
+ }
+
+ //ignore image nodes
+ else if (DataType == typeof(Bitmap))
+ { }
+
+ //add string nodes
+ else
+ {
+ foreach (var v in dataGridViewCells.GroupBy(c => c.Value).OrderBy(g => g.Key))
+ {
+ TreeNodeItemSelector node = TreeNodeItemSelector.CreateNode(v.First().FormattedValue?.ToString(), v.Key, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.Default);
+ ChecklistAddNode(node);
+ }
+ }
+ }
+ }
+
+ ChecklistReloadNodes();
+ }
+
+ ///
+ /// Check if filter buttons needs to be enabled
+ ///
+ private void CheckFilterButtonEnabled()
+ {
+ _buttonFilter.Enabled = HasNodesChecked(_loadedNodes);
+ }
+
+ ///
+ /// Check if selected nodes exists
+ ///
+ ///
+ ///
+ private bool HasNodesChecked(TreeNodeItemSelector?[] nodes)
+ {
+ bool state = false;
+ state = !string.IsNullOrEmpty(_checkTextFilter.Text) ? nodes.Any(n => n!.CheckState == CheckState.Checked && n.Text.ToLower().Contains(_checkTextFilter.Text.ToLower())) : nodes.Any(n => n!.CheckState == CheckState.Checked);
+
+ if (state)
+ {
+ return state;
+ }
+
+ foreach (TreeNodeItemSelector? node in nodes)
+ {
+ foreach (TreeNodeItemSelector nodesel in node!.Nodes)
+ {
+ state = HasNodesChecked([nodesel]);
+ if (state)
+ {
+ break;
+ }
+ }
+ if (state)
+ {
+ break;
+ }
+ }
+
+ return state;
+ }
+
+ ///
+ /// Check
+ ///
+ ///
+ private void NodeCheckChange(TreeNodeItemSelector? node)
+ {
+ if (node != null)
+ {
+ node.CheckState = node.CheckState == CheckState.Checked ? CheckState.Unchecked : CheckState.Checked;
+
+ if (node.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll)
+ {
+ SetNodesCheckState(_loadedNodes, node.Checked);
+ }
+ else
+ {
+ if (node.Nodes.Count > 0)
+ {
+ foreach (TreeNodeItemSelector subnode in node.Nodes)
+ {
+ SetNodesCheckState([subnode], node.Checked);
+ }
+ }
+
+ //refresh nodes
+ CheckState state = UpdateNodesCheckState(ChecklistNodes());
+ GetSelectAllNode()!.CheckState = state;
+ }
+ }
+ }
+
+ ///
+ /// Set Nodes CheckState
+ ///
+ ///
+ ///
+ private void SetNodesCheckState(TreeNodeItemSelector?[] nodes, bool isChecked)
+ {
+ foreach (TreeNodeItemSelector? node in nodes)
+ {
+ node!.Checked = isChecked;
+ if (node.Nodes is { Count: > 0 })
+ {
+ foreach (TreeNodeItemSelector subnode in node.Nodes)
+ {
+ SetNodesCheckState([subnode], isChecked);
+ }
+ }
+
+ }
+ }
+
+ ///
+ /// Update Nodes CheckState recursively
+ ///
+ ///
+ ///
+ private CheckState UpdateNodesCheckState(TreeNodeCollection nodes)
+ {
+ CheckState result = CheckState.Unchecked;
+ bool isFirstNode = true;
+ bool isAllNodesSomeCheckState = true;
+
+ foreach (TreeNodeItemSelector n in nodes.OfType())
+ {
+ if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll)
+ {
+ continue;
+ }
+
+ if (n.Nodes.Count > 0)
+ {
+ n.CheckState = UpdateNodesCheckState(n.Nodes);
+ }
+
+ if (isFirstNode)
+ {
+ result = n.CheckState;
+ isFirstNode = false;
+ }
+ else
+ {
+ if (result != n.CheckState)
+ {
+ isAllNodesSomeCheckState = false;
+ }
+ }
+ }
+
+ return isAllNodesSomeCheckState ? result : CheckState.Indeterminate;
+ }
+
+ ///
+ /// Get the SelectAll Node
+ ///
+ ///
+ private TreeNodeItemSelector? GetSelectAllNode()
+ {
+ TreeNodeItemSelector? result = null;
+ int i = 0;
+ foreach (TreeNodeItemSelector? n in ChecklistNodes().OfType())
+ {
+ if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectAll)
+ {
+ result = n;
+ break;
+ }
+ else if (i > 2)
+ {
+ break;
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Get the SelectEmpty Node
+ ///
+ ///
+ private TreeNodeItemSelector? GetSelectEmptyNode()
+ {
+ TreeNodeItemSelector? result = null;
+ int i = 0;
+ foreach (TreeNodeItemSelector? n in ChecklistNodes().OfType())
+ {
+ if (n.NodeType == TreeNodeItemSelector.CustomNodeType.SelectEmpty)
+ {
+ result = n;
+ break;
+ }
+ else if (i > 2)
+ {
+ break;
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Duplicate Nodes
+ ///
+ private static TreeNodeItemSelector?[] DuplicateNodes(TreeNodeItemSelector?[] nodes)
+ {
+ TreeNodeItemSelector?[] ret = new TreeNodeItemSelector[nodes.Length];
+ int i = 0;
+ foreach (TreeNodeItemSelector? n in nodes)
+ {
+ ret[i] = n?.Clone();
+ i++;
+ }
+ return ret;
+ }
+
+ #endregion
+
+
+ #region checklist filter events
+
+ ///
+ /// CheckList NodeMouseClick event
+ ///
+ ///
+ ///
+ private void CheckList_NodeMouseClick(object? sender, TreeNodeMouseClickEventArgs e)
+ {
+ TreeViewHitTestInfo hitTestInfo = _checkList.HitTest(e.X, e.Y);
+ if (hitTestInfo is { Location: TreeViewHitTestLocations.StateImage })
+ {
+ //check the node check status
+ NodeCheckChange(e.Node as TreeNodeItemSelector);
+ //set filter button enabled
+ CheckFilterButtonEnabled();
+ }
+ }
+
+ ///
+ /// CheckList KeyDown event
+ ///
+ ///
+ ///
+ private void CheckList_KeyDown(object? sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Space)
+ {
+ //check the node check status
+ NodeCheckChange(_checkList.SelectedNode as TreeNodeItemSelector);
+ //set filter button enabled
+ CheckFilterButtonEnabled();
+ }
+ }
+
+ ///
+ /// CheckList NodeMouseDoubleClick event
+ ///
+ ///
+ ///
+ private void CheckList_NodeMouseDoubleClick(object? sender, TreeNodeMouseClickEventArgs e)
+ {
+ TreeNodeItemSelector? n = e.Node as TreeNodeItemSelector;
+ //set the new node check status
+ SetNodesCheckState(_loadedNodes, false);
+ n!.CheckState = CheckState.Unchecked;
+ NodeCheckChange(n);
+ //set filter button enabled
+ CheckFilterButtonEnabled();
+ //do Filter by checkList
+ Button_ok_Click(this, EventArgs.Empty);
+ }
+
+ ///
+ /// CheckList MouseEnter event
+ ///
+ ///
+ ///
+ private void CheckList_MouseEnter(object? sender, EventArgs e)
+ {
+ _checkList.Focus();
+ }
+
+ ///
+ /// CheckList MouseLeave event
+ ///
+ ///
+ ///
+ private void CheckList_MouseLeave(object? sender, EventArgs e)
+ {
+ Focus();
+ }
+
+ ///
+ /// Set the Filter by checkList
+ ///
+ ///
+ ///
+ private void Button_ok_Click(object? sender, EventArgs e)
+ {
+ _filterClick = true;
+
+ SetCheckListFilter();
+ Close();
+ }
+
+ ///
+ /// Undo changed by checkList
+ ///
+ ///
+ ///
+ private void Button_cancel_Click(object? sender, EventArgs e)
+ {
+ _loadedNodes = DuplicateNodes(_startingNodes);
+ Close();
+ }
+
+ #endregion
+
+
+ #region filter methods
+
+ ///
+ /// UnCheck all Custom Filter presets
+ ///
+ private void UnCheckCustomFilters()
+ {
+ for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++)
+ {
+ ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false;
+ }
+ }
+
+ ///
+ /// Set a Custom Filter
+ ///
+ ///
+ private void SetCustomFilter(int filtersMenuItemIndex)
+ {
+ if (_activeFilterType == FilterType.CheckList)
+ {
+ SetNodesCheckState(_loadedNodes, false);
+ }
+
+ ToolStripItem presetItem = _customFilterLastFiltersListMenuItem.DropDownItems[filtersMenuItemIndex];
+ string filterString = presetItem.Tag?.ToString() ?? string.Empty;
+ string viewFilterString = presetItem.Text ?? string.Empty;
+
+ //do preset jobs
+ if (filtersMenuItemIndex != 2)
+ {
+ for (var i = filtersMenuItemIndex; i > 2; i--)
+ {
+ _customFilterLastFiltersListMenuItem.DropDownItems[i].Text = _customFilterLastFiltersListMenuItem.DropDownItems[i - 1].Text;
+ _customFilterLastFiltersListMenuItem.DropDownItems[i].Tag = _customFilterLastFiltersListMenuItem.DropDownItems[i - 1].Tag;
+ }
+
+ _customFilterLastFiltersListMenuItem.DropDownItems[2].Text = viewFilterString;
+ _customFilterLastFiltersListMenuItem.DropDownItems[2].Tag = filterString;
+ }
+
+ // uncheck other preset
+ for (var i = 3; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++)
+ {
+ ((_customFilterLastFiltersListMenuItem.DropDownItems[i] as ToolStripMenuItem)!).Checked = false;
+ }
+
+ ((_customFilterLastFiltersListMenuItem.DropDownItems[2] as ToolStripMenuItem)!).Checked = true;
+ _activeFilterType = FilterType.Custom;
+
+ //get Filter string
+ string? oldFilter = FilterString;
+ FilterString = filterString;
+
+ //set CheckList nodes
+ SetNodesCheckState(_loadedNodes, false);
+
+ _customFilterLastFiltersListMenuItem.Checked = true;
+ _buttonFilter.Enabled = false;
+
+ //fire Filter changed
+ if (oldFilter != FilterString && FilterChanged != null)
+ {
+ FilterChanged(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+
+ #region filter events
+
+ ///
+ /// Cancel Filter Click event
+ ///
+ ///
+ ///
+ private void CancelFilterMenuItem_Click(object? sender, EventArgs e)
+ {
+ string? oldFilter = FilterString;
+
+ //clean Filter
+ CleanFilter();
+
+ //fire Filter changed
+ if (oldFilter != FilterString && FilterChanged != null)
+ {
+ FilterChanged(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Cancel Filter MouseEnter event
+ ///
+ ///
+ ///
+ private void CancelFilterMenuItem_MouseEnter(object? sender, EventArgs e)
+ {
+ if (((sender as ToolStripMenuItem)!).Enabled)
+ {
+ ((sender as ToolStripMenuItem)!).Select();
+ }
+ }
+
+ ///
+ /// Custom Filter Click event
+ ///
+ ///
+ ///
+ private void CustomFilterMenuItem_Click(object? sender, EventArgs e)
+ {
+ //ignore image nodes
+ if (DataType == typeof(Bitmap))
+ {
+ return;
+ }
+
+ //open a new Custom filter window
+ VisualCustomFilterForm flt = new VisualCustomFilterForm(DataType, IsFilterDateAndTimeEnabled);
+
+ if (flt.ShowDialog() == DialogResult.OK)
+ {
+ //add the new Filter presets
+
+ string? filterString = flt.FilterString;
+ string? viewFilterString = flt.FilterStringDescription;
+
+ int index = -1;
+
+ for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++)
+ {
+ if (_customFilterLastFiltersListMenuItem.DropDown.Items[i].Available)
+ {
+ ToolStripItem presetRow = _customFilterLastFiltersListMenuItem.DropDownItems[i];
+ if (string.Equals(presetRow.Text, viewFilterString, StringComparison.Ordinal)
+ && string.Equals(presetRow.Tag?.ToString(), filterString, StringComparison.Ordinal))
+ {
+ index = i;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (index < 2)
+ {
+ for (int i = _customFilterLastFiltersListMenuItem.DropDownItems.Count - 2; i > 1; i--)
+ {
+ if (_customFilterLastFiltersListMenuItem.DropDownItems[i].Available)
+ {
+ _customFilterLastFiltersListMenuItem.DropDownItems[i + 1].Text = _customFilterLastFiltersListMenuItem.DropDownItems[i].Text;
+ _customFilterLastFiltersListMenuItem.DropDownItems[i + 1].Tag = _customFilterLastFiltersListMenuItem.DropDownItems[i].Tag;
+ }
+ }
+ index = 2;
+
+ _customFilterLastFiltersListMenuItem.DropDownItems[2].Text = viewFilterString;
+ _customFilterLastFiltersListMenuItem.DropDownItems[2].Tag = filterString;
+ }
+
+ //set the Custom Filter
+ SetCustomFilter(index);
+ }
+ }
+
+ ///
+ /// Custom Filter preset MouseEnter event
+ ///
+ ///
+ ///
+ private void CustomFilterLastFiltersListMenuItem_MouseEnter(object? sender, EventArgs e)
+ {
+ if (((sender as ToolStripMenuItem)!).Enabled)
+ {
+ ((sender as ToolStripMenuItem)!).Select();
+ }
+ }
+
+ ///
+ /// Custom Filter preset MouseEnter event
+ ///
+ ///
+ ///
+ private void CustomFilterLastFiltersListMenuItem_Paint(object? sender, PaintEventArgs e)
+ {
+ Rectangle rect = new Rectangle(_customFilterLastFiltersListMenuItem.Width - 12, 7, 10, 10);
+ ControlPaint.DrawMenuGlyph(e.Graphics, rect, MenuGlyph.Arrow, Color.Black, Color.Transparent);
+ }
+
+ ///
+ /// Custom Filter preset 1 Visibility changed
+ ///
+ ///
+ ///
+ private void CustomFilterLastFilter1MenuItem_VisibleChanged(object? sender, EventArgs e)
+ {
+ _toolStripSeparator2MenuItem.Visible = !_customFilterLastFilter1MenuItem.Visible;
+ ((sender as ToolStripMenuItem)!).VisibleChanged -= CustomFilterLastFilter1MenuItem_VisibleChanged;
+ }
+
+ ///
+ /// Custom Filter preset Click event
+ ///
+ ///
+ ///
+ private void CustomFilterLastFilterMenuItem_Click(object? sender, EventArgs e)
+ {
+ if (sender is not ToolStripMenuItem menuitem)
+ {
+ return;
+ }
+
+ for (int i = 2; i < _customFilterLastFiltersListMenuItem.DropDownItems.Count; i++)
+ {
+ ToolStripItem presetRow = _customFilterLastFiltersListMenuItem.DropDownItems[i];
+ if (string.Equals(presetRow.Text, menuitem.Text, StringComparison.Ordinal)
+ && string.Equals(presetRow.Tag?.ToString(), menuitem.Tag?.ToString(), StringComparison.Ordinal))
+ {
+ //set current filter preset as active
+ SetCustomFilter(i);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Custom Filter preset TextChanged event
+ ///
+ ///
+ ///
+ private void CustomFilterLastFilterMenuItem_TextChanged(object? sender, EventArgs e)
+ {
+ ((sender as ToolStripMenuItem)!).Available = true;
+ ((sender as ToolStripMenuItem)!).TextChanged -= CustomFilterLastFilterMenuItem_TextChanged;
+ }
+
+ ///
+ /// Text changed timer
+ ///
+ ///
+ ///
+ private void CheckTextFilterTextChangedTimer_Tick(object? sender, EventArgs e)
+ {
+ if (sender is not Timer timer)
+ {
+ return;
+ }
+
+ CheckTextFilterHandleTextChanged(timer.Tag?.ToString() ?? string.Empty);
+
+ timer.Stop();
+ }
+
+ ///
+ /// Check list filter changer
+ ///
+ ///
+ ///
+ private void CheckTextFilter_TextChanged(object? sender, EventArgs e)
+ {
+ if (!_checkTextFilterChangedEnabled)
+ {
+ return;
+ }
+
+ if (_textFilterTextChangedDelayNodes != TextFilterTextChangedDelayNodesDisabled && _loadedNodes.Length > _textFilterTextChangedDelayNodes)
+ {
+ if (_textFilterTextChangedTimer == null)
+ {
+ _textFilterTextChangedTimer = new Timer();
+ _textFilterTextChangedTimer.Tick += new EventHandler(CheckTextFilterTextChangedTimer_Tick);
+ }
+ _textFilterTextChangedTimer.Stop();
+ _textFilterTextChangedTimer.Interval = _textFilterTextChangedDelayMs;
+ _textFilterTextChangedTimer.Tag = _checkTextFilter.Text.ToLower();
+ _textFilterTextChangedTimer.Start();
+ }
+ else
+ {
+ CheckTextFilterHandleTextChanged(_checkTextFilter.Text.ToLower());
+ }
+ }
+
+ ///
+ /// Handle check filter text changed
+ ///
+ ///
+ private void CheckTextFilterHandleTextChanged(string text)
+ {
+ TreeNodeItemSelector allNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectAll)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectAll);
+ TreeNodeItemSelector nullNode = TreeNodeItemSelector.CreateNode(
+ $"{KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewNodeSelectEmpty)]} ", null, CheckState.Checked, TreeNodeItemSelector.CustomNodeType.SelectEmpty);
+ string?[] removedNodesText = [];
+ if (_checkTextFilterRemoveNodesOnSearch)
+ {
+ removedNodesText = _removedSessionNodes.Where(r => !string.IsNullOrEmpty(r?.Text)).Select(r => r?.Text.ToLower()).Distinct().ToArray();
+ }
+ for (int i = _loadedNodes.Length - 1; i >= 0; i--)
+ {
+ TreeNodeItemSelector? node = _loadedNodes[i];
+ if (node?.Text == allNode.Text)
+ {
+ node.CheckState = CheckState.Indeterminate;
+ }
+ else if (node?.Text == nullNode.Text)
+ {
+ node.CheckState = CheckState.Unchecked;
+ }
+ else
+ {
+ if (node != null)
+ {
+ node.CheckState = node.Text.ToLower().Contains(text)
+ ? CheckState.Unchecked
+ : CheckState.Checked;
+
+ if (removedNodesText.Contains(node.Text.ToLower()))
+ {
+ node.CheckState = CheckState.Checked;
+ }
+
+ NodeCheckChange(node);
+ }
+ }
+ }
+ //set filter button enabled
+ CheckFilterButtonEnabled();
+ _removedNodes = _removedSessionNodes;
+ if (_checkTextFilterRemoveNodesOnSearch)
+ {
+ for (int i = _loadedNodes.Length - 1; i >= 0; i--)
+ {
+ TreeNodeItemSelector? node = _loadedNodes[i];
+ if (!(node?.Text == allNode.Text || node?.Text == nullNode.Text))
+ {
+ if (!node!.Text.ToLower().Contains(text))
+ {
+ _removedNodes = _removedNodes.Concat([node]).ToArray();
+ }
+ }
+ }
+ ChecklistReloadNodes();
+ }
+ }
+
+ #endregion
+
+
+ #region sort events
+
+ ///
+ /// Sort ASC Click event
+ ///
+ ///
+ ///
+ private void SortASCMenuItem_Click(object? sender, EventArgs? e)
+ {
+ //ignore image nodes
+ if (DataType == typeof(Bitmap))
+ {
+ return;
+ }
+
+ _sortAscMenuItem.Checked = true;
+ _sortDescMenuItem.Checked = false;
+ _activeSortType = SortType.Asc;
+
+ //get Sort String
+ string? oldSort = SortString;
+ SortString = "[{0}] ASC";
+
+ //fire Sort Changed
+ if (oldSort != SortString && SortChanged != null)
+ {
+ SortChanged(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Sort ASC MouseEnter event
+ ///
+ ///
+ ///
+ private void SortASCMenuItem_MouseEnter(object? sender, EventArgs e)
+ {
+ if (((sender as ToolStripMenuItem)!).Enabled)
+ {
+ ((ToolStripMenuItem)sender).Select();
+ }
+ }
+
+ ///
+ /// Sort DESC Click event
+ ///
+ ///
+ ///
+ private void SortDESCMenuItem_Click(object? sender, EventArgs? e)
+ {
+ //ignore image nodes
+ if (DataType == typeof(Bitmap))
+ {
+ return;
+ }
+
+ _sortAscMenuItem.Checked = false;
+ _sortDescMenuItem.Checked = true;
+ _activeSortType = SortType.Desc;
+
+ //get Sort String
+ string? oldSort = SortString;
+ SortString = "[{0}] DESC";
+
+ //fire Sort Changed
+ if (oldSort != SortString && SortChanged != null)
+ {
+ SortChanged(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Sort DESC MouseEnter event
+ ///
+ ///
+ ///
+ private void SortDESCMenuItem_MouseEnter(object? sender, EventArgs e)
+ {
+ if (((sender as ToolStripMenuItem)!).Enabled)
+ {
+ ((ToolStripMenuItem)sender).Select();
+ }
+ }
+
+ ///
+ /// Cancel Sort Click event
+ ///
+ ///
+ ///
+ private void CancelSortMenuItem_Click(object? sender, EventArgs e)
+ {
+ string? oldSort = SortString;
+ //clean Sort
+ CleanSort();
+ //fire Sort changed
+ if (oldSort != SortString && SortChanged != null)
+ {
+ SortChanged(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Cancel Sort MouseEnter event
+ ///
+ ///
+ ///
+ private void CancelSortMenuItem_MouseEnter(object? sender, EventArgs e)
+ {
+ if (sender is ToolStripMenuItem menuItem && menuItem.Enabled)
+ {
+ menuItem.Select();
+ }
+ }
+
+ #endregion
+
+
+ #region resize methods
+
+ ///
+ /// Get the scaling factor
+ ///
+ ///
+ private float GetScalingFactor()
+ {
+ float ret = 1;
+ using (Graphics gScale = CreateGraphics())
+ {
+ try
+ {
+ ret = gScale.DpiX / 96.0F;
+ }
+ catch (Exception e)
+ {
+ KryptonExceptionHandler.CaptureException(e);
+ }
+ }
+ return ret;
+ }
+
+ ///
+ /// Scale an item
+ ///
+ ///
+ ///
+ ///
+ private static int Scale(int dimension, float factor)
+ {
+ return (int)Math.Floor(dimension * factor);
+ }
+
+ ///
+ /// Resize the box
+ ///
+ ///
+ ///
+ ///
+ private void ResizeBox(int w, int h)
+ {
+ _sortAscMenuItem.Width = w - 1;
+ _sortDescMenuItem.Width = w - 1;
+ _cancelSortMenuItem.Width = w - 1;
+ _cancelFilterMenuItem.Width = w - 1;
+ _customFilterMenuItem.Width = w - 1;
+ _customFilterLastFiltersListMenuItem.Width = w - 1;
+ _checkTextFilterControlHost.Width = w - 35;
+
+ //scale objects using original width and height
+ float scalingFactor = GetScalingFactor();
+ int w2 = (int)Math.Round(w / scalingFactor, 0);
+ int h2 = (int)Math.Round(h / scalingFactor, 0);
+ _checkFilterListControlHost.Size = new Size(Scale(w2 - 35, scalingFactor), Scale(h2 - 160 - 25, scalingFactor));
+ _checkFilterListPanel.Size = _checkFilterListControlHost.Size;
+ _checkList.Bounds = new Rectangle(Scale(4, scalingFactor), Scale(4, scalingFactor), Scale(w2 - 35 - 8, scalingFactor), Scale(h2 - 160 - 25 - 8, scalingFactor));
+ _checkFilterListButtonsControlHost.Size = new Size(Scale(w2 - 35, scalingFactor), Scale(24, scalingFactor));
+ _buttonFilter.Location = new Point(Scale(w2 - 35 - 164, scalingFactor), 0);
+ _buttonUndofilter.Location = new Point(Scale(w2 - 35 - 79, scalingFactor), 0);
+ _resizeBoxControlHost.Margin = new Padding(Scale(w2 - 46, scalingFactor), 0, 0, 0);
+
+ //get all objects height to make sure we have room for the grip
+ int finalHeight =
+ _sortAscMenuItem.Height +
+ _sortDescMenuItem.Height +
+ _cancelSortMenuItem.Height +
+ _cancelFilterMenuItem.Height +
+ _toolStripSeparator1MenuItem.Height +
+ _toolStripSeparator2MenuItem.Height +
+ _customFilterLastFiltersListMenuItem.Height +
+ _toolStripSeparator3MenuItem.Height +
+ _checkFilterListControlHost.Height +
+ _checkTextFilterControlHost.Height +
+ _checkFilterListButtonsControlHost.Height +
+ _resizeBoxControlHost.Height;
+
+ // apply the needed height only when scaled
+ Size = Math.Abs(scalingFactor - 1) < 1 ? new Size(w, h) : new Size(w, h + (finalHeight - h < 0 ? 0 : finalHeight - h));
+ }
+
+ ///
+ /// Clean box for Resize
+ ///
+ private void ResizeClean()
+ {
+ if (_resizeEndPoint.X != -1)
+ {
+ Point startPoint = PointToScreen(_resizeStartPoint);
+
+ Rectangle rc = new Rectangle(startPoint.X, startPoint.Y, _resizeEndPoint.X, _resizeEndPoint.Y)
+ {
+ X = Math.Min(startPoint.X, _resizeEndPoint.X),
+ Width = Math.Abs(startPoint.X - _resizeEndPoint.X),
+
+ Y = Math.Min(startPoint.Y, _resizeEndPoint.Y),
+ Height = Math.Abs(startPoint.Y - _resizeEndPoint.Y)
+ };
+
+ ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Dashed);
+
+ _resizeEndPoint.X = -1;
+ }
+ }
+
+ #endregion
+
+
+ #region resize events
+
+ ///
+ /// Resize MouseDown event
+ ///
+ ///
+ ///
+ private void ResizeBoxControlHost_MouseDown(object? sender, MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ ResizeClean();
+ }
+ }
+
+ ///
+ /// Resize MouseMove event
+ ///
+ ///
+ ///
+ private void ResizeBoxControlHost_MouseMove(object? sender, MouseEventArgs e)
+ {
+ if (Visible)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ int x = e.X;
+ int y = e.Y;
+
+ ResizeClean();
+
+ x += Width - _resizeBoxControlHost.Width;
+ y += Height - _resizeBoxControlHost.Height;
+
+ x = Math.Max(x, MinimumSize.Width - 1);
+ y = Math.Max(y, MinimumSize.Height - 1);
+
+ Point startPoint = PointToScreen(_resizeStartPoint);
+ Point endPoint = PointToScreen(new Point(x, y));
+
+ Rectangle rc = new Rectangle
+ {
+ X = Math.Min(startPoint.X, endPoint.X),
+ Width = Math.Abs(startPoint.X - endPoint.X),
+
+ Y = Math.Min(startPoint.Y, endPoint.Y),
+ Height = Math.Abs(startPoint.Y - endPoint.Y)
+ };
+
+ ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Dashed);
+
+ _resizeEndPoint.X = endPoint.X;
+ _resizeEndPoint.Y = endPoint.Y;
+ }
+ }
+ }
+
+ ///
+ /// Resize MouseUp event
+ ///
+ ///
+ ///
+ private void ResizeBoxControlHost_MouseUp(object? sender, MouseEventArgs e)
+ {
+ if (_resizeEndPoint.X != -1)
+ {
+ ResizeClean();
+
+ if (Visible)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ int newWidth = e.X + Width - _resizeBoxControlHost.Width;
+ int newHeight = e.Y + Height - _resizeBoxControlHost.Height;
+
+ newWidth = Math.Max(newWidth, MinimumSize.Width);
+ newHeight = Math.Max(newHeight, MinimumSize.Height);
+
+ ResizeBox(newWidth, newHeight);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Resize Paint event
+ ///
+ ///
+ ///
+ private void ResizeBoxControlHost_Paint(object? sender, PaintEventArgs e)
+ {
+ e.Graphics.DrawImage(Properties.Resources.MenuStrip_ResizeGrip, 0, 0);
+ }
+
+ #endregion
+
+}
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs
new file mode 100644
index 0000000000..04dd178dac
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Toolkit/TreeNodeItemSelector.cs
@@ -0,0 +1,191 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+internal class TreeNodeItemSelector : TreeNode
+{
+ #region public enum
+
+ public enum CustomNodeType : byte
+ {
+ Default,
+ SelectAll,
+ SelectEmpty,
+ DateTimeNode
+ }
+
+ #endregion
+
+
+ #region class properties
+
+ private CheckState _checkState = CheckState.Unchecked;
+ private TreeNodeItemSelector? _parent;
+
+ #endregion
+
+
+ #region constructor
+
+ ///
+ /// TreeNodeItemSelector constructor
+ ///
+ ///
+ ///
+ ///
+ ///
+ private TreeNodeItemSelector(string? text, object? value, CheckState state, CustomNodeType nodeType)
+ : base(text)
+ {
+ CheckState = state;
+ NodeType = nodeType;
+ Value = value;
+ }
+
+ #endregion
+
+
+ #region public clone method
+
+ ///
+ /// Clone a Node
+ ///
+ ///
+ public new TreeNodeItemSelector Clone()
+ {
+ TreeNodeItemSelector n = new TreeNodeItemSelector(Text, Value, _checkState, NodeType)
+ {
+ NodeFont = NodeFont
+ };
+
+ if (GetNodeCount(false) > 0)
+ {
+ foreach (TreeNodeItemSelector? child in Nodes)
+ {
+ if (child != null)
+ {
+ n.AddChild(child.Clone());
+ }
+ }
+ }
+
+ return n;
+ }
+
+ #endregion
+
+
+ #region public getters / setters
+
+ ///
+ /// Get Node NodeType
+ ///
+ public CustomNodeType NodeType { get; private set; }
+
+ ///
+ /// Get Node value
+ ///
+ public object? Value { get; private set; }
+
+ ///
+ /// Get Node parent
+ ///
+ public new TreeNodeItemSelector? Parent
+ {
+ get => _parent;
+ set => _parent = value;
+ }
+
+ ///
+ /// Node is Checked
+ ///
+ public new bool Checked
+ {
+ get => _checkState == CheckState.Checked;
+ set => CheckState = value ? CheckState.Checked : CheckState.Unchecked;
+ }
+
+ ///
+ /// Get or Set the current Node CheckState
+ ///
+ public CheckState CheckState
+ {
+ get => _checkState;
+ set
+ {
+ _checkState = value;
+ StateImageIndex = _checkState switch
+ {
+ CheckState.Checked => 1,
+ CheckState.Indeterminate => 2,
+ _ => 0
+ };
+ }
+ }
+
+ #endregion
+
+
+ #region public create nodes methods
+
+ ///
+ /// Create a Node
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static TreeNodeItemSelector CreateNode(string? text, object? value, CheckState state, CustomNodeType type)
+ {
+ return new TreeNodeItemSelector(text, value, state, type);
+ }
+
+ ///
+ /// Create a child Node
+ ///
+ ///
+ ///
+ ///
+ ///
+ public TreeNodeItemSelector? CreateChildNode(string? text, object? value, CheckState state)
+ {
+ TreeNodeItemSelector? n = null;
+
+ //specific method for datetimenode
+ if (NodeType == CustomNodeType.DateTimeNode)
+ {
+ n = new TreeNodeItemSelector(text, value, state, CustomNodeType.DateTimeNode);
+ }
+
+ if (n != null)
+ {
+ AddChild(n);
+ }
+
+ return n;
+ }
+ public TreeNodeItemSelector? CreateChildNode(string? text, object? value)
+ {
+ return CreateChildNode(text, value, _checkState);
+ }
+
+ ///
+ /// Add a child Node to this Node
+ ///
+ ///
+ protected void AddChild(TreeNodeItemSelector? child)
+ {
+ child!.Parent = this;
+ Nodes.Add(child);
+ }
+
+ #endregion
+}
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs
new file mode 100644
index 0000000000..8e6773eeee
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.Designer.cs
@@ -0,0 +1,176 @@
+namespace Krypton.Utilities
+{
+ partial class VisualCustomFilterForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.kryptonPanel1 = new Krypton.Toolkit.KryptonPanel();
+ this.button_cancel = new Krypton.Toolkit.KryptonButton();
+ this.button_ok = new Krypton.Toolkit.KryptonButton();
+ this.kryptonBorderEdge1 = new Krypton.Toolkit.KryptonBorderEdge();
+ this.kryptonPanel2 = new Krypton.Toolkit.KryptonPanel();
+ this.label_columnName = new Krypton.Toolkit.KryptonLabel();
+ this.comboBox_filterType = new Krypton.Toolkit.KryptonComboBox();
+ this.label_and = new Krypton.Toolkit.KryptonLabel();
+ this.ep = new Krypton.Toolkit.KryptonErrorProvider(this.components);
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).BeginInit();
+ this.kryptonPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).BeginInit();
+ this.kryptonPanel2.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.comboBox_filterType)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ep)).BeginInit();
+ this.SuspendLayout();
+ //
+ // kryptonPanel1
+ //
+ this.kryptonPanel1.Controls.Add(this.button_cancel);
+ this.kryptonPanel1.Controls.Add(this.button_ok);
+ this.kryptonPanel1.Controls.Add(this.kryptonBorderEdge1);
+ this.kryptonPanel1.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.kryptonPanel1.Location = new System.Drawing.Point(0, 126);
+ this.kryptonPanel1.Name = "kryptonPanel1";
+ this.kryptonPanel1.PanelBackStyle = Krypton.Toolkit.PaletteBackStyle.PanelAlternate;
+ this.kryptonPanel1.Size = new System.Drawing.Size(205, 50);
+ this.kryptonPanel1.TabIndex = 1;
+ //
+ // button_cancel
+ //
+ this.button_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.button_cancel.Location = new System.Drawing.Point(118, 15);
+ this.button_cancel.Name = "button_cancel";
+ this.button_cancel.Size = new System.Drawing.Size(75, 23);
+ this.button_cancel.TabIndex = 3;
+ this.button_cancel.Values.Text = "Cancel";
+ this.button_cancel.Click += new System.EventHandler(this.button_cancel_Click);
+ //
+ // button_ok
+ //
+ this.button_ok.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.button_ok.Location = new System.Drawing.Point(37, 15);
+ this.button_ok.Name = "button_ok";
+ this.button_ok.Size = new System.Drawing.Size(75, 23);
+ this.button_ok.TabIndex = 2;
+ this.button_ok.Values.Text = "OK";
+ this.button_ok.Click += new System.EventHandler(this.button_ok_Click);
+ //
+ // kryptonBorderEdge1
+ //
+ this.kryptonBorderEdge1.BorderStyle = Krypton.Toolkit.PaletteBorderStyle.HeaderSecondary;
+ this.kryptonBorderEdge1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.kryptonBorderEdge1.Location = new System.Drawing.Point(0, 0);
+ this.kryptonBorderEdge1.Name = "kryptonBorderEdge1";
+ this.kryptonBorderEdge1.Size = new System.Drawing.Size(205, 1);
+ this.kryptonBorderEdge1.Text = "kryptonBorderEdge1";
+ //
+ // kryptonPanel2
+ //
+ this.kryptonPanel2.Controls.Add(this.label_columnName);
+ this.kryptonPanel2.Controls.Add(this.comboBox_filterType);
+ this.kryptonPanel2.Controls.Add(this.label_and);
+ this.kryptonPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kryptonPanel2.Location = new System.Drawing.Point(0, 0);
+ this.kryptonPanel2.Name = "kryptonPanel2";
+ this.kryptonPanel2.Size = new System.Drawing.Size(205, 126);
+ this.kryptonPanel2.TabIndex = 2;
+ //
+ // label_columnName
+ //
+ this.label_columnName.LabelStyle = Krypton.Toolkit.LabelStyle.NormalPanel;
+ this.label_columnName.Location = new System.Drawing.Point(6, 13);
+ this.label_columnName.Name = "label_columnName";
+ this.label_columnName.Size = new System.Drawing.Size(138, 20);
+ this.label_columnName.TabIndex = 7;
+ this.label_columnName.Values.Text = "Show rows where value";
+ //
+ // comboBox_filterType
+ //
+ this.comboBox_filterType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboBox_filterType.DropDownWidth = 189;
+ this.comboBox_filterType.FormattingEnabled = true;
+ this.comboBox_filterType.IntegralHeight = false;
+ this.comboBox_filterType.Location = new System.Drawing.Point(9, 39);
+ this.comboBox_filterType.Name = "comboBox_filterType";
+ this.comboBox_filterType.Size = new System.Drawing.Size(189, 21);
+ this.comboBox_filterType.TabIndex = 8;
+ this.comboBox_filterType.SelectedIndexChanged += new System.EventHandler(this.comboBox_filterType_SelectedIndexChanged);
+ //
+ // label_and
+ //
+ this.label_and.LabelStyle = Krypton.Toolkit.LabelStyle.NormalPanel;
+ this.label_and.Location = new System.Drawing.Point(9, 93);
+ this.label_and.Name = "label_and";
+ this.label_and.Size = new System.Drawing.Size(33, 20);
+ this.label_and.TabIndex = 9;
+ this.label_and.Values.Text = "And";
+ this.label_and.Visible = false;
+ //
+ // ep
+ //
+ this.ep.ContainerControl = this;
+ //
+ // FormCustomFilter
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(205, 176);
+ this.Controls.Add(this.kryptonPanel2);
+ this.Controls.Add(this.kryptonPanel1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormCustomFilter";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Custom Filter";
+ this.Controls.SetChildIndex(this.kryptonPanel1, 0);
+ this.Controls.SetChildIndex(this.kryptonPanel2, 0);
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).EndInit();
+ this.kryptonPanel1.ResumeLayout(false);
+ this.kryptonPanel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).EndInit();
+ this.kryptonPanel2.ResumeLayout(false);
+ this.kryptonPanel2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.comboBox_filterType)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ep)).EndInit();
+ this.ResumeLayout(false);
+ }
+
+ #endregion
+
+ private KryptonPanel kryptonPanel1;
+ private KryptonBorderEdge kryptonBorderEdge1;
+ private KryptonButton button_cancel;
+ private KryptonButton button_ok;
+ private KryptonPanel kryptonPanel2;
+ private KryptonLabel label_columnName;
+ private KryptonComboBox comboBox_filterType;
+ private KryptonLabel label_and;
+ private KryptonErrorProvider ep;
+ }
+}
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs
new file mode 100644
index 0000000000..98e8f4ec89
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.cs
@@ -0,0 +1,527 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+public partial class VisualCustomFilterForm : KryptonForm
+{
+ #region Instance Fields
+
+ private readonly FilterType _filterType;
+ private Control? _valControl1;
+ private Control? _valControl2;
+
+ private readonly bool _filterDateAndTimeEnabled;
+
+ private string? _filterString;
+
+ private string? _filterStringDescription;
+
+ #endregion
+
+ #region Public
+
+ ///
+ /// Get the Filter string
+ ///
+ public string? FilterString => _filterString;
+
+ ///
+ /// Get the Filter string description
+ ///
+ public string? FilterStringDescription => _filterStringDescription;
+
+ #endregion
+
+ #region Identity
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Type of the data.
+ /// if set to true [filter date and time enabled].
+ public VisualCustomFilterForm(Type dataType, bool filterDateAndTimeEnabled)
+ {
+ InitializeComponent();
+
+ //set component translations
+ Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFormTitle)];
+ label_columnName.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLabelColumnNameText)];
+ label_and.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLabelAnd)];
+ button_ok.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonOk)];
+ button_cancel.Text = KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewButtonCancel)];
+
+ _filterType = dataType switch
+ {
+ _ when dataType == typeof(DateTime) => FilterType.DateTime,
+ _ when dataType == typeof(TimeSpan) => FilterType.TimeSpan,
+ _ when dataType == typeof(int) || dataType == typeof(long) || dataType == typeof(short) ||
+ dataType == typeof(uint) || dataType == typeof(ulong) || dataType == typeof(ushort) ||
+ dataType == typeof(byte) || dataType == typeof(sbyte) => FilterType.Integer,
+ _ when dataType == typeof(float) || dataType == typeof(double) || dataType == typeof(decimal) => FilterType.Float,
+ _ when dataType == typeof(string) => FilterType.String,
+ _ => FilterType.Unknown
+ };
+
+ _filterDateAndTimeEnabled = filterDateAndTimeEnabled;
+
+ switch (_filterType)
+ {
+ case FilterType.DateTime:
+ _valControl1 = new DateTimePicker();
+ _valControl2 = new DateTimePicker();
+ if (_filterDateAndTimeEnabled)
+ {
+ DateTimeFormatInfo dt = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
+
+ (_valControl1 as DateTimePicker)!.CustomFormat = $@"{dt.ShortDatePattern} HH:mm";
+ (_valControl2 as DateTimePicker)!.CustomFormat = $@"{dt.ShortDatePattern} HH:mm";
+ (_valControl1 as DateTimePicker)!.Format = DateTimePickerFormat.Custom;
+ (_valControl2 as DateTimePicker)!.Format = DateTimePickerFormat.Custom;
+ }
+ else
+ {
+ (_valControl1 as DateTimePicker)!.Format = DateTimePickerFormat.Short;
+ (_valControl2 as DateTimePicker)!.Format = DateTimePickerFormat.Short;
+ }
+
+ comboBox_filterType.Items.AddRange([
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)]
+ ]);
+ break;
+
+ case FilterType.TimeSpan:
+ _valControl1 = new TextBox();
+ _valControl2 = new TextBox();
+ comboBox_filterType.Items.AddRange([
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)]
+ ]);
+ break;
+
+ case FilterType.Integer:
+ case FilterType.Float:
+ _valControl1 = new TextBox();
+ _valControl2 = new TextBox();
+ _valControl1.TextChanged += valControl_TextChanged;
+ _valControl2.TextChanged += valControl_TextChanged;
+ comboBox_filterType.Items.AddRange([
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)]
+ ]);
+ _valControl1.Tag = true;
+ _valControl2.Tag = true;
+ button_ok.Enabled = false;
+ break;
+
+ default:
+ _valControl1 = new TextBox();
+ _valControl2 = new TextBox();
+ comboBox_filterType.Items.AddRange([
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)],
+ KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)]
+ ]);
+ break;
+ }
+ comboBox_filterType.SelectedIndex = 0;
+
+ _valControl1.Name = "valControl1";
+ _valControl1.Location = new(20, 66);
+ _valControl1.Size = new(166, 20);
+ _valControl1.Width = comboBox_filterType.Width - 20;
+ _valControl1.TabIndex = 4;
+ _valControl1.Visible = true;
+ _valControl1.KeyDown += valControl_KeyDown;
+
+ _valControl2.Name = "valControl2";
+ _valControl2.Location = new(20, 108);
+ _valControl2.Size = new(166, 20);
+ _valControl2.Width = comboBox_filterType.Width - 20;
+ _valControl2.TabIndex = 5;
+ _valControl2.Visible = false;
+ _valControl2.VisibleChanged += valControl2_VisibleChanged;
+ _valControl2.KeyDown += valControl_KeyDown;
+
+ Controls.Add(_valControl1);
+ Controls.Add(_valControl2);
+
+ ep.SetIconAlignment(_valControl1, KryptonErrorIconAlignment.MiddleRight);
+ ep.SetIconPadding(_valControl1, -18);
+ ep.SetIconAlignment(_valControl2, KryptonErrorIconAlignment.MiddleRight);
+ ep.SetIconPadding(_valControl2, -18);
+ }
+
+ #endregion
+
+ #region Implementation
+
+ ///
+ /// Build a Filter string
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private string? BuildCustomFilter(FilterType filterType, bool filterDateAndTimeEnabled, string filterTypeConditionText, Control control1, Control control2)
+ {
+ string? filterString;
+
+ string? column = @"[{0}] ";
+
+ if (filterType == FilterType.Unknown)
+ {
+ column = $"Convert([{{0}}], 'System.String') ";
+ }
+
+ filterString = column;
+
+ switch (filterType)
+ {
+ case FilterType.DateTime:
+ DateTime dt = ((DateTimePicker)control1).Value;
+ dt = new(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);
+
+ if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)])
+ {
+ filterString =
+ $"Convert([{{0}}], 'System.String') LIKE '%{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}%'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThan)])
+ {
+ filterString +=
+ $"< '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEarlierThanOrEqualTo)])
+ {
+ filterString +=
+ $"<= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThan)])
+ {
+ filterString +=
+ $"> '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLaterThanOrEqualTo)])
+ {
+ filterString +=
+ $">= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)])
+ {
+ DateTime dt1 = ((DateTimePicker)control2).Value;
+ dt1 = new(dt1.Year, dt1.Month, dt1.Day, dt1.Hour, dt1.Minute, 0);
+ filterString +=
+ $">= '{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}'";
+ filterString +=
+ $" AND {column}<= '{Convert.ToString(filterDateAndTimeEnabled ? dt1 : dt1.Date, CultureInfo.CurrentCulture)}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)])
+ {
+ filterString =
+ $"Convert([{{0}}], 'System.String') NOT LIKE '%{Convert.ToString(filterDateAndTimeEnabled ? dt : dt.Date, CultureInfo.CurrentCulture)}%'";
+ }
+
+ break;
+
+ case FilterType.TimeSpan:
+ try
+ {
+ TimeSpan ts = TimeSpan.Parse(control1.Text);
+
+ if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)])
+ {
+ filterString =
+ $"(Convert([{{0}}], 'System.String') LIKE '%P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}%')";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)])
+ {
+ filterString =
+ $"(Convert([{{0}}], 'System.String') NOT LIKE '%P{(ts.Days > 0 ? $"{ts.Days}D" : "")}{(ts.TotalHours > 0 ? "T" : "")}{(ts.Hours > 0 ? $"{ts.Hours}H" : "")}{(ts.Minutes > 0 ? $"{ts.Minutes}M" : "")}{(ts.Seconds > 0 ? $"{ts.Seconds}S" : "")}%')";
+ }
+ }
+ catch (FormatException)
+ {
+ filterString = null;
+ }
+ break;
+
+ case FilterType.Integer:
+ case FilterType.Float:
+
+ string num = control1.Text;
+
+ if (filterType == FilterType.Float)
+ {
+ num = num.Replace(",", ".");
+ }
+
+ if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)])
+ {
+ filterString += $"= {num}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)])
+ {
+ filterString +=
+ $">= {num} AND {column}<= {(filterType == FilterType.Float ? control2.Text.Replace(",", ".") : control2.Text)}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)])
+ {
+ filterString += $"<> {num}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThan)])
+ {
+ filterString += $"> {num}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewGreaterThanOrEqualTo)])
+ {
+ filterString += $">= {num}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThan)])
+ {
+ filterString += $"< {num}";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewLessThanOrEqualTo)])
+ {
+ filterString += $"<= {num}";
+ }
+
+ break;
+
+ default:
+ string txt = FormatFilterString(control1.Text);
+ if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEquals)])
+ {
+ filterString += $"LIKE '{txt}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEqual)])
+ {
+ filterString += $"NOT LIKE '{txt}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewBeginsWith)])
+ {
+ filterString += $"LIKE '{txt}%'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewEndsWith)])
+ {
+ filterString += $"LIKE '%{txt}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotBeginWith)])
+ {
+ filterString += $"NOT LIKE '{txt}%'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotEndWith)])
+ {
+ filterString += $"NOT LIKE '%{txt}'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewContains)])
+ {
+ filterString += $"LIKE '%{txt}%'";
+ }
+ else if (filterTypeConditionText == KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewDoesNotContain)])
+ {
+ filterString += $"NOT LIKE '%{txt}%'";
+ }
+
+ break;
+ }
+
+ return filterString;
+ }
+
+ ///
+ /// Format a text Filter string
+ ///
+ ///
+ ///
+ private string FormatFilterString(string text)
+ {
+ string result = "";
+ string s;
+ string[] replace = ["%", "[", "]", "*", "\"", "\\"];
+
+ for (int i = 0; i < text.Length; i++)
+ {
+ s = text[i].ToString();
+ if (replace.Contains(s))
+ {
+ result += $"[{s}]";
+ }
+ else
+ {
+ result += s;
+ }
+ }
+
+ return result.Replace("'", "''");
+ }
+
+ private void button_cancel_Click(object sender, EventArgs e)
+ {
+ _filterStringDescription = null;
+ _filterString = null;
+ DialogResult = DialogResult.Cancel;
+ }
+
+ private void button_ok_Click(object sender, EventArgs e)
+ {
+ if (_valControl1 != null && _valControl2 != null && ((_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) ||
+ (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag)))
+ {
+ button_ok.Enabled = false;
+ return;
+ }
+
+ if (_valControl1 != null)
+ {
+ if (_valControl2 != null)
+ {
+ string? filterString = BuildCustomFilter(_filterType, _filterDateAndTimeEnabled, comboBox_filterType.Text, _valControl1, _valControl2);
+
+ if (!String.IsNullOrEmpty(filterString))
+ {
+ _filterString = filterString;
+ _filterStringDescription = string.Format(KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewFilterStringDescription)], comboBox_filterType.Text, _valControl1.Text);
+ if (_valControl2.Visible)
+ {
+ _filterStringDescription += $" {label_and.Text} \"{_valControl2.Text}\"";
+ }
+
+ DialogResult = DialogResult.OK;
+ }
+ else
+ {
+ _filterString = null;
+ _filterStringDescription = null;
+ DialogResult = DialogResult.Cancel;
+ }
+ }
+ }
+
+ Close();
+ }
+
+ private void comboBox_filterType_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (_valControl2 != null)
+ {
+ _valControl2.Visible = comboBox_filterType.Text ==
+ KryptonAdvancedDataGridView.Translations[
+ nameof(TranslationKey.KryptonAdvancedDataGridViewBetween)];
+ if (_valControl1 != null)
+ {
+ button_ok.Enabled =
+ !(_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) ||
+ (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag);
+ }
+ }
+ }
+
+ ///
+ /// Changed control2 visibility
+ ///
+ ///
+ ///
+ private void valControl2_VisibleChanged(object? sender, EventArgs e)
+ {
+ if (_valControl2 != null)
+ {
+ label_and.Visible = _valControl2.Visible;
+ }
+ }
+
+ ///
+ /// Changed a control Text
+ ///
+ ///
+ ///
+ private void valControl_TextChanged(object? sender, EventArgs e)
+ {
+ bool hasErrors = false;
+ switch (_filterType)
+ {
+ case FilterType.Integer:
+ long val;
+ hasErrors = !long.TryParse((sender as TextBox)!.Text, out val);
+ break;
+
+ case FilterType.Float:
+ double val1;
+ hasErrors = !double.TryParse((sender as TextBox)!.Text, out val1);
+ break;
+ }
+
+ (sender as Control)!.Tag = hasErrors || (sender as TextBox)!.Text.Length == 0;
+
+ if (hasErrors && (sender as TextBox)!.Text.Length > 0)
+ {
+ ep.SetError((sender as Control)!, KryptonAdvancedDataGridView.Translations[nameof(TranslationKey.KryptonAdvancedDataGridViewInvalidValue)]);
+ }
+ else
+ {
+ ep.SetError((sender as Control)!, "");
+ }
+
+ if (_valControl1 != null && _valControl2 != null)
+ {
+ button_ok.Enabled = !(_valControl1.Visible && _valControl1.Tag != null && (bool)_valControl1.Tag) ||
+ (_valControl2.Visible && _valControl2.Tag != null && (bool)_valControl2.Tag);
+ }
+ }
+
+ ///
+ /// KeyDown on a control
+ ///
+ ///
+ ///
+ private void valControl_KeyDown(object? sender, KeyEventArgs e)
+ {
+ if (e.KeyData == Keys.Enter)
+ {
+ if (sender == _valControl1)
+ {
+ if (_valControl2 is { Visible: true })
+ {
+ _valControl2.Focus();
+ }
+ else
+ {
+ button_ok_Click(button_ok, EventArgs.Empty);
+ }
+ }
+ else
+ {
+ button_ok_Click(button_ok, EventArgs.Empty);
+ }
+
+ e.SuppressKeyPress = false;
+ e.Handled = true;
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx
new file mode 100644
index 0000000000..1af7de150c
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/Controls Visuals/VisualCustomFilterForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs
new file mode 100644
index 0000000000..8fa85b60a7
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/AdvancedDataGridViewSearchToolBarSearchEventArgs.cs
@@ -0,0 +1,64 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+public class AdvancedDataGridViewSearchToolBarSearchEventArgs : EventArgs
+{
+ /// Gets the value to search.
+ /// The value to search.
+ public string ValueToSearch { get; private set; }
+
+ ///
+ /// Gets the column to search.
+ ///
+ ///
+ /// The column to search.
+ ///
+ public DataGridViewColumn? ColumnToSearch { get; private set; }
+
+ ///
+ /// Gets a value indicating whether [case sensitive].
+ ///
+ ///
+ /// true if [case sensitive]; otherwise, false.
+ ///
+ public bool CaseSensitive { get; private set; }
+
+ ///
+ /// Gets a value indicating whether [whole word].
+ ///
+ ///
+ /// true if [whole word]; otherwise, false.
+ ///
+ public bool WholeWord { get; private set; }
+
+ ///
+ /// Gets a value indicating whether [from begin].
+ ///
+ ///
+ /// true if [from begin]; otherwise, false.
+ ///
+ public bool FromBegin { get; private set; }
+
+ /// Initializes a new instance of the class.
+ /// The value.
+ /// The column.
+ /// if set to true [case].
+ /// if set to true [whole].
+ /// if set to true [from begin].
+ public AdvancedDataGridViewSearchToolBarSearchEventArgs(string value, DataGridViewColumn? column, bool @case, bool whole, bool fromBegin)
+ {
+ ValueToSearch = value;
+ ColumnToSearch = column;
+ CaseSensitive = @case;
+ WholeWord = whole;
+ FromBegin = fromBegin;
+ }
+}
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs
new file mode 100644
index 0000000000..30014c4331
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/EventArgs/ColumnHeaderCellEventArgs.cs
@@ -0,0 +1,33 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+internal class ColumnHeaderCellEventArgs : EventArgs
+{
+ public MenuStrip? FilterMenu { get; private set; }
+
+ public DataGridViewColumn Column { get; private set; }
+
+ #region Identity
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The filter menu.
+ /// The column.
+ public ColumnHeaderCellEventArgs(MenuStrip? filterMenu, DataGridViewColumn column)
+ {
+ FilterMenu = filterMenu;
+
+ Column = column;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs
new file mode 100644
index 0000000000..7d137a386d
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/AdvancedDataGridViewSearchToolBarSearchEventHandler.cs
@@ -0,0 +1,17 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+///
+///
+///
+/// The sender.
+/// The instance containing the event data.
+public delegate void AdvancedDataGridViewSearchToolBarSearchEventHandler(object sender, AdvancedDataGridViewSearchToolBarSearchEventArgs e);
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs
new file mode 100644
index 0000000000..1be3acd159
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/ColumnHeaderCellEventHandler.cs
@@ -0,0 +1,17 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+///
+///
+///
+/// The sender.
+/// The instance containing the event data.
+internal delegate void ColumnHeaderCellEventHandler(object sender, ColumnHeaderCellEventArgs e);
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs
new file mode 100644
index 0000000000..de058980b4
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/Definitions.cs
@@ -0,0 +1,283 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+#region Enum FilterType
+
+///
+/// Specifies the category of filtering to apply for a column or value.
+///
+public enum FilterType
+{
+ ///
+ /// The filter type is unknown or not specified.
+ ///
+ Unknown,
+
+ ///
+ /// Filter applies to values.
+ ///
+ DateTime,
+
+ ///
+ /// Filter applies to values.
+ ///
+ TimeSpan,
+
+ ///
+ /// Filter applies to textual/string values.
+ ///
+ String,
+
+ ///
+ /// Filter applies to floating point numeric values.
+ ///
+ Float,
+
+ ///
+ /// Filter applies to integer numeric values.
+ ///
+ Integer
+}
+
+#endregion
+
+#region Enum TranslationKey
+
+///
+/// Available translation keys for KryptonAdvancedDataGridView UI strings.
+///
+public enum TranslationKey
+{
+ ///
+ /// Sort by date/time ascending.
+ ///
+ KryptonAdvancedDataGridViewSortDateTimeAscending,
+
+ ///
+ /// Sort by date/time descending.
+ ///
+ KryptonAdvancedDataGridViewSortDateTimeDescending,
+
+ ///
+ /// Sort boolean values with false then true.
+ ///
+ KryptonAdvancedDataGridViewSortBoolAscending,
+
+ ///
+ /// Sort boolean values with true then false.
+ ///
+ KryptonAdvancedDataGridViewSortBoolDescending,
+
+ ///
+ /// Sort numeric values ascending.
+ ///
+ KryptonAdvancedDataGridViewSortNumAscending,
+
+ ///
+ /// Sort numeric values descending.
+ ///
+ KryptonAdvancedDataGridViewSortNumDescending,
+
+ ///
+ /// Sort text values ascending (A-Z).
+ ///
+ KryptonAdvancedDataGridViewSortTextAscending,
+
+ ///
+ /// Sort text values descending (Z-A).
+ ///
+ KryptonAdvancedDataGridViewSortTextDescending,
+
+ ///
+ /// Add a custom filter.
+ ///
+ KryptonAdvancedDataGridViewAddCustomFilter,
+
+ ///
+ /// Label for a custom filter.
+ ///
+ KryptonAdvancedDataGridViewCustomFilter,
+
+ ///
+ /// Clear the active filter.
+ ///
+ KryptonAdvancedDataGridViewClearFilter,
+
+ ///
+ /// Clear the active sort.
+ ///
+ KryptonAdvancedDataGridViewClearSort,
+
+ ///
+ /// Text for the filter button.
+ ///
+ KryptonAdvancedDataGridViewButtonFilter,
+
+ ///
+ /// Text for the undo filter button.
+ ///
+ KryptonAdvancedDataGridViewButtonUndoFilter,
+
+ ///
+ /// Select all nodes in checklist filter.
+ ///
+ KryptonAdvancedDataGridViewNodeSelectAll,
+
+ ///
+ /// Select empty/null nodes in checklist filter.
+ ///
+ KryptonAdvancedDataGridViewNodeSelectEmpty,
+
+ ///
+ /// Select nodes with true values in checklist filter.
+ ///
+ KryptonAdvancedDataGridViewNodeSelectTrue,
+
+ ///
+ /// Select nodes with false values in checklist filter.
+ ///
+ KryptonAdvancedDataGridViewNodeSelectFalse,
+
+ ///
+ /// Disable checklist filter.
+ ///
+ KryptonAdvancedDataGridViewFilterChecklistDisable,
+
+ ///
+ /// Equality operator label.
+ ///
+ KryptonAdvancedDataGridViewEquals,
+
+ ///
+ /// Inequality operator label.
+ ///
+ KryptonAdvancedDataGridViewDoesNotEqual,
+
+ ///
+ /// Earlier than operator label.
+ ///
+ KryptonAdvancedDataGridViewEarlierThan,
+
+ ///
+ /// Earlier than or equal to operator label.
+ ///
+ KryptonAdvancedDataGridViewEarlierThanOrEqualTo,
+
+ ///
+ /// Later than operator label.
+ ///
+ KryptonAdvancedDataGridViewLaterThan,
+
+ ///
+ /// Later than or equal to operator label.
+ ///
+ KryptonAdvancedDataGridViewLaterThanOrEqualTo,
+
+ ///
+ /// Between operator label.
+ ///
+ KryptonAdvancedDataGridViewBetween,
+
+ ///
+ /// Greater than operator label.
+ ///
+ KryptonAdvancedDataGridViewGreaterThan,
+
+ ///
+ /// Greater than or equal to operator label.
+ ///
+ KryptonAdvancedDataGridViewGreaterThanOrEqualTo,
+
+ ///
+ /// Less than operator label.
+ ///
+ KryptonAdvancedDataGridViewLessThan,
+
+ ///
+ /// Less than or equal to operator label.
+ ///
+ KryptonAdvancedDataGridViewLessThanOrEqualTo,
+
+ ///
+ /// Begins with operator label.
+ ///
+ KryptonAdvancedDataGridViewBeginsWith,
+
+ ///
+ /// Does not begin with operator label.
+ ///
+ KryptonAdvancedDataGridViewDoesNotBeginWith,
+
+ ///
+ /// Ends with operator label.
+ ///
+ KryptonAdvancedDataGridViewEndsWith,
+
+ ///
+ /// Does not end with operator label.
+ ///
+ KryptonAdvancedDataGridViewDoesNotEndWith,
+
+ ///
+ /// Contains operator label.
+ ///
+ KryptonAdvancedDataGridViewContains,
+
+ ///
+ /// Does not contain operator label.
+ ///
+ KryptonAdvancedDataGridViewDoesNotContain,
+
+ ///
+ /// Invalid value message.
+ ///
+ KryptonAdvancedDataGridViewInvalidValue,
+
+ ///
+ /// Description for string filter UI.
+ ///
+ KryptonAdvancedDataGridViewFilterStringDescription,
+
+ ///
+ /// Title for the filter form.
+ ///
+ KryptonAdvancedDataGridViewFormTitle,
+
+ ///
+ /// Label for column name text.
+ ///
+ KryptonAdvancedDataGridViewLabelColumnNameText,
+
+ ///
+ /// Label for logical AND between conditions.
+ ///
+ KryptonAdvancedDataGridViewLabelAnd,
+
+ ///
+ /// Text for the "OK" button in the advanced data grid view filter form.
+ ///
+ KryptonAdvancedDataGridViewButtonOk,
+
+ ///
+ /// Text for the "Cancel" button in the advanced data grid view filter form.
+ ///
+ KryptonAdvancedDataGridViewButtonCancel,
+ ADGVSTBLabelSearch,
+ ADGVSTBButtonFromBegin,
+ ADGVSTBButtonCaseSensitiveToolTip,
+ ADGVSTBButtonSearchToolTip,
+ ADGVSTBButtonCloseToolTip,
+ ADGVSTBButtonWholeWordToolTip,
+ ADGVSTBComboBoxColumnsAll,
+ ADGVSTBTextBoxSearchToolTip
+}
+
+#endregion
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs
new file mode 100644
index 0000000000..8183a61ccc
--- /dev/null
+++ b/Source/Krypton Components/Krypton.Utilities/Components/KryptonAdvancedDataGridView/General/KryptonColumnHeaderCell.cs
@@ -0,0 +1,715 @@
+#region BSD License
+/*
+ *
+ * New BSD 3-Clause License (https://github.com/Krypton-Suite/Standard-Toolkit/blob/master/LICENSE)
+ * Modifications by Peter Wagner (aka Wagnerp), Simon Coghlan (aka Smurf-IV), Giduac, Ahmed Abdelhameed, tobitege, KamaniAR, Lesandro Gotardo (aka lesandrog), Jorge A. Avilés (aka mcpbcs) et al. 2026 - 2026. All rights reserved.
+ *
+ */
+#endregion
+
+namespace Krypton.Utilities;
+
+internal class KryptonColumnHeaderCell : DataGridViewColumnHeaderCell
+{
+ #region Instance Fields
+
+ private Image _filterImage = Properties.Resources.ColumnHeader_UnFiltered;
+ private Size _filterButtonImageSize = new Size(16, 16);
+ private bool _filterButtonPressed = false;
+ private bool _filterButtonOver = false;
+ private Rectangle _filterButtonOffsetBounds = Rectangle.Empty;
+ private Rectangle _filterButtonImageBounds = Rectangle.Empty;
+ private Padding _filterButtonMargin = new Padding(3, 4, 3, 4);
+ private bool _filterEnabled = false;
+
+ ///
+ /// Get the MenuStrip for this ColumnHeaderCell
+ ///
+ public MenuStrip? MenuStrip { get; private set; }
+
+
+ #endregion
+
+ #region Constants
+
+ ///
+ /// Default behaviour for Date and Time filter
+ ///
+ private const bool FILTER_DATE_AND_TIME_DEFAULT_ENABLED = false;
+
+ #endregion
+
+ #region Events
+
+ public event ColumnHeaderCellEventHandler? FilterPopup;
+ public event ColumnHeaderCellEventHandler? SortChanged;
+ public event ColumnHeaderCellEventHandler? FilterChanged;
+
+ #endregion
+
+ #region Identity
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The old cell.
+ /// if set to true [filter enabled].
+ public KryptonColumnHeaderCell(DataGridViewColumnHeaderCell oldCell, bool filterEnabled) : base()
+ {
+ Tag = oldCell.Tag;
+
+ ErrorText = oldCell.ErrorText;
+
+ ToolTipText = oldCell.ToolTipText;
+
+ Value = oldCell.Value;
+
+ ValueType = oldCell.ValueType;
+
+ ContextMenuStrip = oldCell.ContextMenuStrip;
+
+ Style = oldCell.Style;
+
+ _filterEnabled = filterEnabled;
+
+ if (oldCell is KryptonColumnHeaderCell { MenuStrip: not null } oldCellt)
+ {
+ MenuStrip = oldCellt.MenuStrip;
+ _filterImage = oldCellt._filterImage;
+ _filterButtonPressed = oldCellt._filterButtonPressed;
+ _filterButtonOver = oldCellt._filterButtonOver;
+ _filterButtonOffsetBounds = oldCellt._filterButtonOffsetBounds;
+ _filterButtonImageBounds = oldCellt._filterButtonImageBounds;
+ MenuStrip.FilterChanged += new EventHandler(MenuStrip_FilterChanged);
+ MenuStrip.SortChanged += new EventHandler(MenuStrip_SortChanged);
+ }
+ else
+ {
+ Type dataType = oldCell.OwningColumn?.ValueType ?? typeof(object);
+ MenuStrip = new MenuStrip(dataType);
+ MenuStrip.FilterChanged += new EventHandler(MenuStrip_FilterChanged);
+ MenuStrip.SortChanged += new EventHandler(MenuStrip_SortChanged);
+ }
+
+ IsFilterDateAndTimeEnabled = FILTER_DATE_AND_TIME_DEFAULT_ENABLED;
+ IsSortEnabled = true;
+ IsFilterEnabled = true;
+ IsFilterChecklistEnabled = true;
+ }
+
+ ~KryptonColumnHeaderCell()
+ {
+ if (MenuStrip != null)
+ {
+ MenuStrip.FilterChanged -= MenuStrip_FilterChanged;
+ MenuStrip.SortChanged -= MenuStrip_SortChanged;
+ }
+ }
+
+ #endregion
+
+ #region Implementation
+
+ ///
+ /// Get or Set the Filter and Sort enabled status
+ ///
+ public bool FilterAndSortEnabled
+ {
+ get => _filterEnabled;
+ set
+ {
+ if (!value)
+ {
+ _filterButtonPressed = false;
+ _filterButtonOver = false;
+ }
+
+ if (value != _filterEnabled)
+ {
+ _filterEnabled = value;
+ bool refreshed = false;
+ if (MenuStrip?.FilterString!.Length > 0)
+ {
+ MenuStrip_FilterChanged(this, EventArgs.Empty);
+ refreshed = true;
+ }
+ if (MenuStrip?.SortString!.Length > 0)
+ {
+ MenuStrip_SortChanged(this, EventArgs.Empty);
+ refreshed = true;
+ }
+ if (!refreshed)
+ {
+ RepaintCell();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Set or Unset the Filter and Sort to Loaded mode
+ ///
+ ///
+ public void SetLoadedMode(bool enabled)
+ {
+ MenuStrip?.SetLoadedMode(enabled);
+ RefreshImage();
+ RepaintCell();
+ }
+
+ ///
+ /// Clean Sort
+ ///
+ public void CleanSort()
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ MenuStrip.CleanSort();
+ RefreshImage();
+ RepaintCell();
+ }
+ }
+
+ ///
+ /// Clean Filter
+ ///
+ public void CleanFilter()
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ MenuStrip.CleanFilter();
+ RefreshImage();
+ RepaintCell();
+ }
+ }
+
+ ///
+ /// Sort ASC
+ ///
+ public void SortASC()
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ MenuStrip.SortAsc();
+ }
+ }
+
+ ///
+ /// Sort DESC
+ ///
+ public void SortDESC()
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ MenuStrip.SortDesc();
+ }
+ }
+
+ ///
+ /// Clone the ColumnHeaderCell
+ ///
+ ///
+ public override object Clone()
+ {
+ return new KryptonColumnHeaderCell(this, FilterAndSortEnabled);
+ }
+
+ ///
+ /// Get the MenuStrip SortType
+ ///
+ public MenuStrip.SortType ActiveSortType
+ {
+ get
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ return MenuStrip.ActiveSortType;
+ }
+ else
+ {
+ return MenuStrip.SortType.None;
+ }
+ }
+ }
+
+ ///
+ /// Get the MenuStrip FilterType
+ ///
+ public MenuStrip.FilterType ActiveFilterType
+ {
+ get
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ return MenuStrip.ActiveFilterType;
+ }
+ else
+ {
+ return MenuStrip.FilterType.None;
+ }
+ }
+ }
+
+ ///
+ /// Get the Sort string
+ ///
+ public string? SortString
+ {
+ get
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ return MenuStrip.SortString;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ }
+
+ ///
+ /// Get the Filter string
+ ///
+ public string? FilterString
+ {
+ get
+ {
+ if (MenuStrip != null && FilterAndSortEnabled)
+ {
+ return MenuStrip.FilterString;
+ }
+ else
+ {
+ return "";
+ }
+ }
+ }
+
+ ///
+ /// Get the Minimum size
+ ///
+ public Size MinimumSize =>
+ new(_filterButtonImageSize.Width + _filterButtonMargin.Left + _filterButtonMargin.Right,
+ _filterButtonImageSize.Height + _filterButtonMargin.Bottom + _filterButtonMargin.Top);
+
+ ///
+ /// Get or Set the Sort enabled status
+ ///
+ public bool IsSortEnabled
+ {
+ get => MenuStrip is { IsSortEnabled: true };
+ set => MenuStrip?.IsSortEnabled = value;
+ }
+
+ ///
+ /// Get or Set the Filter enabled status
+ ///
+ public bool IsFilterEnabled
+ {
+ get => MenuStrip is { IsFilterEnabled: true };
+ set => MenuStrip?.IsFilterEnabled = value;
+ }
+
+ ///
+ /// Get or Set the Filter enabled status
+ ///
+ public bool IsFilterChecklistEnabled
+ {
+ get => MenuStrip is { IsFilterChecklistEnabled: true };
+ set => MenuStrip?.IsFilterChecklistEnabled = value;
+ }
+
+ ///
+ /// Get or Set the FilterDateAndTime enabled status
+ ///
+ public bool IsFilterDateAndTimeEnabled
+ {
+ get => MenuStrip is { IsFilterDateAndTimeEnabled: true };
+ set => MenuStrip?.IsFilterDateAndTimeEnabled = value;
+ }
+
+ ///
+ /// Get or Set the NOT IN logic for Filter
+ ///
+ public bool IsMenuStripFilterNOTINLogicEnabled
+ {
+ get => MenuStrip is { IsFilterNotinLogicEnabled: true };
+ set => MenuStrip?.IsFilterNotinLogicEnabled = value;
+ }
+
+ ///
+ /// Set the text filter search nodes behaviour
+ ///
+ public bool DoesTextFilterRemoveNodesOnSearch
+ {
+ get => MenuStrip is { DoesTextFilterRemoveNodesOnSearch: true };
+ set => MenuStrip?.DoesTextFilterRemoveNodesOnSearch = value;
+ }
+
+ ///
+ /// Number of nodes to enable the TextChanged delay on text filter
+ ///
+ public int TextFilterTextChangedDelayNodes
+ {
+ get => MenuStrip!.TextFilterTextChangedDelayNodes;
+ set => MenuStrip?.TextFilterTextChangedDelayNodes = value;
+ }
+
+ ///
+ /// Enabled or disable Sort capabilities
+ ///
+ ///
+ public void SetSortEnabled(bool enabled)
+ {
+ if (MenuStrip != null)
+ {
+ MenuStrip.IsSortEnabled = enabled;
+ MenuStrip.SetSortEnabled(enabled);
+ }
+ }
+
+ ///
+ /// Enable or disable Filter capabilities
+ ///
+ ///
+ public void SetFilterEnabled(bool enabled)
+ {
+ if (MenuStrip != null)
+ {
+ MenuStrip.IsFilterEnabled = enabled;
+ MenuStrip.SetFilterEnabled(enabled);
+ }
+ }
+
+ ///
+ /// Enable or disable Filter checklist capabilities
+ ///
+ ///
+ public void SetFilterChecklistEnabled(bool enabled)
+ {
+ if (MenuStrip != null)
+ {
+ MenuStrip.IsFilterChecklistEnabled = enabled;
+ MenuStrip.SetFilterChecklistEnabled(enabled);
+ }
+ }
+
+ ///
+ /// Set Filter checklist nodes max
+ ///
+ ///
+ public void SetFilterChecklistNodesMax(int maxNodes)
+ {
+ if (maxNodes >= 0)
+ {
+ MenuStrip?.MaxChecklistNodes = maxNodes;
+ }
+ }
+
+ ///
+ /// Enable or disable Filter checklist nodes max
+ ///
+ ///
+ public void EnabledFilterChecklistNodesMax(bool enabled)
+ {
+ if (MenuStrip is { MaxChecklistNodes: 0 } && enabled)
+ {
+ MenuStrip.MaxChecklistNodes = MenuStrip.DefaultMaxChecklistNodes;
+ }
+ else if (MenuStrip is not { MaxChecklistNodes: 0 } && !enabled)
+ {
+ MenuStrip?.MaxChecklistNodes = 0;
+ }
+ }
+
+ ///
+ /// Enable or disable Filter custom capabilities
+ ///
+ ///
+ public void SetFilterCustomEnabled(bool enabled)
+ {
+ if (MenuStrip != null)
+ {
+ MenuStrip.IsFilterCustomEnabled = enabled;
+ MenuStrip.SetFilterCustomEnabled(enabled);
+ }
+ }
+
+ ///
+ /// Enable or disable Text filter on checklist remove node mode
+ ///
+ ///
+ public void SetChecklistTextFilterRemoveNodesOnSearchMode(bool enabled) => MenuStrip?.SetChecklistTextFilterRemoveNodesOnSearchMode(enabled);
+
+ ///
+ /// Disable text filter TextChanged delay
+ ///
+ public void SetTextFilterTextChangedDelayNodesDisabled() => MenuStrip?.SetTextFilterTextChangedDelayNodesDisabled();
+
+ ///
+ /// Set text filter TextChanged delay milliseconds
+ ///
+ public void SetTextFilterTextChangedDelayMs(int milliseconds) => MenuStrip?.TextFilterTextChangedDelayMs = milliseconds;
+
+ #endregion
+
+ #region MenuStrip Events
+
+ ///
+ /// OnFilterChanged event
+ ///
+ ///
+ ///
+ private void MenuStrip_FilterChanged(object? sender, EventArgs e)
+ {
+ RefreshImage();
+ RepaintCell();
+ if (FilterAndSortEnabled && FilterChanged != null && OwningColumn != null)
+ {
+ FilterChanged(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn));
+ }
+ }
+
+ ///
+ /// OnSortChanged event
+ ///
+ ///
+ ///
+ private void MenuStrip_SortChanged(object? sender, EventArgs e)
+ {
+ RefreshImage();
+ RepaintCell();
+ if (FilterAndSortEnabled && SortChanged != null && OwningColumn != null)
+ {
+ SortChanged(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn));
+ }
+ }
+
+ ///
+ /// Clean attached events
+ ///
+ public void CleanEvents()
+ {
+ MenuStrip?.FilterChanged -= MenuStrip_FilterChanged;
+ MenuStrip?.SortChanged -= MenuStrip_SortChanged;
+ }
+
+
+ #endregion
+
+ #region Paint Methods
+
+ ///
+ /// Repaint the Cell
+ ///
+ private void RepaintCell()
+ {
+ if (Displayed && DataGridView != null)
+ {
+ DataGridView.InvalidateCell(this);
+ }
+ }
+
+ ///
+ /// Refresh the Cell image
+ ///
+ private void RefreshImage()
+ {
+ if (ActiveFilterType == MenuStrip.FilterType.Loaded)
+ {
+ _filterImage = Properties.Resources.ColumnHeader_SavedFilters;
+ }
+ else
+ {
+ if (ActiveFilterType == MenuStrip.FilterType.None)
+ {
+ if (ActiveSortType == MenuStrip.SortType.None)
+ {
+ _filterImage = Properties.Resources.ColumnHeader_UnFiltered;
+ }
+ else if (ActiveSortType == MenuStrip.SortType.Asc)
+ {
+ _filterImage = Properties.Resources.ColumnHeader_OrderedASC;
+ }
+ else
+ {
+ _filterImage = Properties.Resources.ColumnHeader_OrderedDESC;
+ }
+ }
+ else
+ {
+ if (ActiveSortType == MenuStrip.SortType.None)
+ {
+ _filterImage = Properties.Resources.ColumnHeader_Filtered;
+ }
+ else if (ActiveSortType == MenuStrip.SortType.Asc)
+ {
+ _filterImage = Properties.Resources.ColumnHeader_FilteredAndOrderedASC;
+ }
+ else
+ {
+ _filterImage = Properties.Resources.ColumnHeader_FilteredAndOrderedDESC;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Pain method
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected override void Paint(
+ Graphics graphics,
+ Rectangle clipBounds,
+ Rectangle cellBounds,
+ int rowIndex,
+ DataGridViewElementStates cellState,
+ object? value,
+ object? formattedValue,
+ string? errorText,
+ DataGridViewCellStyle cellStyle,
+ DataGridViewAdvancedBorderStyle advancedBorderStyle,
+ DataGridViewPaintParts paintParts)
+ {
+ if (SortGlyphDirection != SortOrder.None)
+ {
+ SortGlyphDirection = SortOrder.None;
+ }
+
+ base.Paint(graphics, clipBounds, cellBounds, rowIndex,
+ cellState, value, formattedValue,
+ errorText, cellStyle, advancedBorderStyle, paintParts);
+
+ // By default, skip Bitmap columns unless KryptonAdvancedDataGridView.FilterAndSortOnBitmapColumns is true
+ if (OwningColumn?.ValueType == typeof(Bitmap) &&
+ (DataGridView is not KryptonAdvancedDataGridView advancedGrid || !advancedGrid.FilterAndSortOnBitmapColumns))
+ {
+ return;
+ }
+
+ if (FilterAndSortEnabled && paintParts.HasFlag(DataGridViewPaintParts.ContentBackground))
+ {
+ _filterButtonOffsetBounds = GetFilterBounds(true);
+ _filterButtonImageBounds = GetFilterBounds(false);
+ Rectangle buttonBounds = _filterButtonOffsetBounds;
+ if (clipBounds.IntersectsWith(buttonBounds))
+ {
+ ControlPaint.DrawBorder(graphics, buttonBounds, Color.Gray, ButtonBorderStyle.Solid);
+ buttonBounds.Inflate(-1, -1);
+ using (Brush b = new SolidBrush(_filterButtonOver ? Color.WhiteSmoke : Color.White))
+ graphics.FillRectangle(b, buttonBounds);
+ graphics.DrawImage(_filterImage, buttonBounds);
+ }
+ }
+ }
+
+ ///
+ /// Get the ColumnHeaderCell Bounds
+ ///
+ ///
+ ///
+ private Rectangle GetFilterBounds(bool withOffset = true)
+ {
+ Rectangle cell = DataGridView!.GetCellDisplayRectangle(ColumnIndex, -1, false);
+
+ Point p = new Point(
+ (withOffset ? cell.Right : cell.Width) - _filterButtonImageSize.Width - _filterButtonMargin.Right,
+ (withOffset ? cell.Bottom : cell.Height) - _filterButtonImageSize.Height - _filterButtonMargin.Bottom);
+
+ return new Rectangle(p, _filterButtonImageSize);
+ }
+
+ #endregion
+
+ #region Mouse Events
+
+ ///
+ /// OnMouseMove event
+ ///
+ ///
+ protected override void OnMouseMove(DataGridViewCellMouseEventArgs e)
+ {
+ if (FilterAndSortEnabled)
+ {
+ if (_filterButtonImageBounds.Contains(e.X, e.Y) && !_filterButtonOver)
+ {
+ _filterButtonOver = true;
+ RepaintCell();
+ }
+ else if (!_filterButtonImageBounds.Contains(e.X, e.Y) && _filterButtonOver)
+ {
+ _filterButtonOver = false;
+ RepaintCell();
+ }
+ }
+ base.OnMouseMove(e);
+ }
+
+ ///
+ /// OnMouseDown event
+ ///
+ ///
+ protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
+ {
+ if (FilterAndSortEnabled && _filterButtonImageBounds.Contains(e.X, e.Y))
+ {
+ if (e.Button == MouseButtons.Left && !_filterButtonPressed)
+ {
+ _filterButtonPressed = true;
+ _filterButtonOver = true;
+ RepaintCell();
+ }
+ }
+ else
+ {
+ base.OnMouseDown(e);
+ }
+ }
+
+ ///
+ /// OnMouseUp event
+ ///
+ ///
+ protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
+ {
+ if (FilterAndSortEnabled && e.Button == MouseButtons.Left && _filterButtonPressed)
+ {
+ _filterButtonPressed = false;
+ _filterButtonOver = false;
+ RepaintCell();
+ if (_filterButtonImageBounds.Contains(e.X, e.Y) && FilterPopup != null && OwningColumn != null)
+ {
+ FilterPopup(this, new ColumnHeaderCellEventArgs(MenuStrip, OwningColumn));
+ }
+ }
+ base.OnMouseUp(e);
+ }
+
+ ///
+ /// OnMouseLeave event
+ ///
+ ///
+ protected override void OnMouseLeave(int rowIndex)
+ {
+ if (FilterAndSortEnabled && _filterButtonOver)
+ {
+ _filterButtonOver = false;
+ RepaintCell();
+ }
+
+ base.OnMouseLeave(rowIndex);
+ }
+
+ #endregion
+}
diff --git a/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs b/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs
index 547799c493..18bab5378f 100644
--- a/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs
+++ b/Source/Krypton Components/Krypton.Utilities/Global/Globals.cs
@@ -10,12 +10,17 @@
global using System;
global using System.Collections.Concurrent;
global using System.ComponentModel;
+global using System.Data;
global using System.Diagnostics;
global using System.Diagnostics.CodeAnalysis;
global using System.Drawing;
+global using System.Net;
+global using System.Net.Http;
global using System.Security.Cryptography;
+global using System.Text;
global using System.Windows.Forms;
global using System.Windows.Forms.Design;
+global using System.Xml.Serialization;
global using Krypton.Navigator;
global using Krypton.Ribbon;
diff --git a/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs b/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs
deleted file mode 100644
index fcb44bd76b..0000000000
--- a/Source/Krypton Components/Krypton.Utilities/GlobalUsings.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Global using directives
-
-global using System;
-global using System.Net.Http;
-global using System.Net;
-global using System.Text;
-global using System.Xml.Serialization;
\ No newline at end of file
diff --git a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs
index d5e41d1dba..9951530dd5 100644
--- a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs
+++ b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.Designer.cs
@@ -90,6 +90,76 @@ internal static System.Drawing.Bitmap Cancel_Windows_11 {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_Filtered {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_Filtered", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_FilteredAndOrderedASC {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_FilteredAndOrderedASC", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_FilteredAndOrderedDESC {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_FilteredAndOrderedDESC", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_OrderedASC {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_OrderedASC", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_OrderedDESC {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_OrderedDESC", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_SavedFilters {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_SavedFilters", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap ColumnHeader_UnFiltered {
+ get {
+ object obj = ResourceManager.GetObject("ColumnHeader_UnFiltered", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -220,6 +290,76 @@ internal static System.Drawing.Bitmap Krypton_Stable {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderASCbool {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderASCbool", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderASCnum {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderASCnum", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderASCtxt {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderASCtxt", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderDESCbool {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderDESCbool", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderDESCnum {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderDESCnum", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_OrderDESCtxt {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_OrderDESCtxt", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuStrip_ResizeGrip {
+ get {
+ object obj = ResourceManager.GetObject("MenuStrip_ResizeGrip", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -280,6 +420,56 @@ internal static System.Drawing.Bitmap Restart_Dark {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap SearchToolBar_ButtonCaseSensitive {
+ get {
+ object obj = ResourceManager.GetObject("SearchToolBar_ButtonCaseSensitive", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap SearchToolBar_ButtonClose {
+ get {
+ object obj = ResourceManager.GetObject("SearchToolBar_ButtonClose", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap SearchToolBar_ButtonFromBegin {
+ get {
+ object obj = ResourceManager.GetObject("SearchToolBar_ButtonFromBegin", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap SearchToolBar_ButtonSearch {
+ get {
+ object obj = ResourceManager.GetObject("SearchToolBar_ButtonSearch", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap SearchToolBar_ButtonWholeWord {
+ get {
+ object obj = ResourceManager.GetObject("SearchToolBar_ButtonWholeWord", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx
index e83225b85c..ba60dd6208 100644
--- a/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx
+++ b/Source/Krypton Components/Krypton.Utilities/Properties/Resources.resx
@@ -127,6 +127,27 @@
..\Resources\Cancel_Windows_11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Resources\ColumnHeader_Filtered.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_FilteredAndOrderedASC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_FilteredAndOrderedDESC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_OrderedASC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_OrderedDESC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_SavedFilters.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\ColumnHeader_UnFiltered.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Resources\Copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
@@ -166,6 +187,27 @@
..\Resources\Krypton Stable.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Resources\MenuStrip_OrderASCbool.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_OrderASCnum.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_OrderASCtxt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_OrderDESCbool.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_OrderDESCnum.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_OrderDESCtxt.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\MenuStrip_ResizeGrip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Resources\Ok.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
@@ -184,6 +226,21 @@
..\Resources\Restart_Dark.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Resources\SearchToolBar_ButtonCaseSensitive.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\SearchToolBar_ButtonClose.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\SearchToolBar_ButtonFromBegin.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\SearchToolBar_ButtonSearch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\SearchToolBar_ButtonWholeWord.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Resources\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png
new file mode 100644
index 0000000000..30031fce7a
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_Filtered.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png
new file mode 100644
index 0000000000..9b89940fcb
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedASC.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedDESC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedDESC.png
new file mode 100644
index 0000000000..fee011d8c4
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_FilteredAndOrderedDESC.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png
new file mode 100644
index 0000000000..d6625f04b3
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedASC.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png
new file mode 100644
index 0000000000..c4b15dc748
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_OrderedDESC.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_SavedFilters.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_SavedFilters.png
new file mode 100644
index 0000000000..5933f82e97
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_SavedFilters.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png
new file mode 100644
index 0000000000..16b306fb3c
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/ColumnHeader_UnFiltered.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png
new file mode 100644
index 0000000000..75c518b589
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCbool.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png
new file mode 100644
index 0000000000..ebc3a3ec81
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCnum.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCtxt.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCtxt.png
new file mode 100644
index 0000000000..d42346d22c
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderASCtxt.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCbool.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCbool.png
new file mode 100644
index 0000000000..1db26ad672
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCbool.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png
new file mode 100644
index 0000000000..cd03b10615
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCnum.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCtxt.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCtxt.png
new file mode 100644
index 0000000000..d3d722e4b7
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_OrderDESCtxt.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_ResizeGrip.png b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_ResizeGrip.png
new file mode 100644
index 0000000000..79b228daa2
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/MenuStrip_ResizeGrip.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonCaseSensitive.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonCaseSensitive.png
new file mode 100644
index 0000000000..814fe452af
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonCaseSensitive.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png
new file mode 100644
index 0000000000..17c03870f9
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonClose.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonFromBegin.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonFromBegin.png
new file mode 100644
index 0000000000..8835185ec3
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonFromBegin.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png
new file mode 100644
index 0000000000..03d9e50f0d
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonSearch.png differ
diff --git a/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonWholeWord.png b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonWholeWord.png
new file mode 100644
index 0000000000..44fccadaf1
Binary files /dev/null and b/Source/Krypton Components/Krypton.Utilities/Resources/SearchToolBar_ButtonWholeWord.png differ
diff --git a/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.Designer.cs b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.Designer.cs
new file mode 100644
index 0000000000..5a92663134
--- /dev/null
+++ b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.Designer.cs
@@ -0,0 +1,401 @@
+namespace TestForm
+{
+ partial class AdvancedDataGridViewTest
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.kryptonPanel1 = new Krypton.Toolkit.KryptonPanel();
+ this.kbtnApplySavedFilters = new Krypton.Toolkit.KryptonButton();
+ this.kbtnClearFilters = new Krypton.Toolkit.KryptonButton();
+ this.kbtnSaveFilters = new Krypton.Toolkit.KryptonButton();
+ this.kryptonLabel6 = new Krypton.Toolkit.KryptonLabel();
+ this.kryptonLabel5 = new Krypton.Toolkit.KryptonLabel();
+ this.kcmbSortSaved = new Krypton.Toolkit.KryptonComboBox();
+ this.kcmbSavedFilters = new Krypton.Toolkit.KryptonComboBox();
+ this.ktxtStringFilter = new Krypton.Toolkit.KryptonTextBox();
+ this.kryptonLabel4 = new Krypton.Toolkit.KryptonLabel();
+ this.ktxtSortString = new Krypton.Toolkit.KryptonTextBox();
+ this.kryptonLabel2 = new Krypton.Toolkit.KryptonLabel();
+ this.ktxtFilterString = new Krypton.Toolkit.KryptonTextBox();
+ this.kryptonLabel1 = new Krypton.Toolkit.KryptonLabel();
+ this.kcmbMemoryTest = new Krypton.Toolkit.KryptonComboBox();
+ this.kbtnMemoryTest = new Krypton.Toolkit.KryptonButton();
+ this.kbtnLoadRandomData = new Krypton.Toolkit.KryptonButton();
+ this.kryptonPanel2 = new Krypton.Toolkit.KryptonPanel();
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.tsslMemoryUsage = new System.Windows.Forms.ToolStripStatusLabel();
+ this.kryptonPanel3 = new Krypton.Toolkit.KryptonPanel();
+ this.ktxtTotalRows = new Krypton.Toolkit.KryptonTextBox();
+ this.kryptonLabel3 = new Krypton.Toolkit.KryptonLabel();
+ this.kryptonPanel4 = new Krypton.Toolkit.KryptonPanel();
+ this.kadgvMain = new Krypton.Utilities.KryptonAdvancedDataGridView();
+ this.kryptonAdvancedDataGridViewSearchToolBar1 = new Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar();
+ this.bsData = new System.Windows.Forms.BindingSource(this.components);
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).BeginInit();
+ this.kryptonPanel1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbSortSaved)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbSavedFilters)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbMemoryTest)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).BeginInit();
+ this.kryptonPanel2.SuspendLayout();
+ this.statusStrip1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel3)).BeginInit();
+ this.kryptonPanel3.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel4)).BeginInit();
+ this.kryptonPanel4.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kadgvMain)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.bsData)).BeginInit();
+ this.SuspendLayout();
+ //
+ // kryptonPanel1
+ //
+ this.kryptonPanel1.Controls.Add(this.kbtnApplySavedFilters);
+ this.kryptonPanel1.Controls.Add(this.kbtnClearFilters);
+ this.kryptonPanel1.Controls.Add(this.kbtnSaveFilters);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel6);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel5);
+ this.kryptonPanel1.Controls.Add(this.kcmbSortSaved);
+ this.kryptonPanel1.Controls.Add(this.kcmbSavedFilters);
+ this.kryptonPanel1.Controls.Add(this.ktxtStringFilter);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel4);
+ this.kryptonPanel1.Controls.Add(this.ktxtSortString);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel2);
+ this.kryptonPanel1.Controls.Add(this.ktxtFilterString);
+ this.kryptonPanel1.Controls.Add(this.kryptonLabel1);
+ this.kryptonPanel1.Controls.Add(this.kcmbMemoryTest);
+ this.kryptonPanel1.Controls.Add(this.kbtnMemoryTest);
+ this.kryptonPanel1.Controls.Add(this.kbtnLoadRandomData);
+ this.kryptonPanel1.Dock = System.Windows.Forms.DockStyle.Top;
+ this.kryptonPanel1.Location = new System.Drawing.Point(0, 0);
+ this.kryptonPanel1.Name = "kryptonPanel1";
+ this.kryptonPanel1.Size = new System.Drawing.Size(1108, 189);
+ this.kryptonPanel1.TabIndex = 0;
+ //
+ // kbtnApplySavedFilters
+ //
+ this.kbtnApplySavedFilters.Location = new System.Drawing.Point(1005, 72);
+ this.kbtnApplySavedFilters.Name = "kbtnApplySavedFilters";
+ this.kbtnApplySavedFilters.Size = new System.Drawing.Size(90, 25);
+ this.kbtnApplySavedFilters.TabIndex = 15;
+ this.kbtnApplySavedFilters.Values.Text = "Apply";
+ this.kbtnApplySavedFilters.Click += new System.EventHandler(this.kbtnApplySavedFilters_Click);
+ //
+ // kbtnClearFilters
+ //
+ this.kbtnClearFilters.Location = new System.Drawing.Point(669, 45);
+ this.kbtnClearFilters.Name = "kbtnClearFilters";
+ this.kbtnClearFilters.Size = new System.Drawing.Size(179, 25);
+ this.kbtnClearFilters.TabIndex = 14;
+ this.kbtnClearFilters.Values.Text = "Clean Filter And Sort";
+ this.kbtnClearFilters.Click += new System.EventHandler(this.kbtnClearFilters_Click);
+ //
+ // kbtnSaveFilters
+ //
+ this.kbtnSaveFilters.Location = new System.Drawing.Point(669, 13);
+ this.kbtnSaveFilters.Name = "kbtnSaveFilters";
+ this.kbtnSaveFilters.Size = new System.Drawing.Size(180, 25);
+ this.kbtnSaveFilters.TabIndex = 13;
+ this.kbtnSaveFilters.Values.Text = "Save Current Filter And Sort";
+ this.kbtnSaveFilters.Click += new System.EventHandler(this.kbtnSaveFilters_Click);
+ //
+ // kryptonLabel6
+ //
+ this.kryptonLabel6.Location = new System.Drawing.Point(860, 40);
+ this.kryptonLabel6.Name = "kryptonLabel6";
+ this.kryptonLabel6.Size = new System.Drawing.Size(71, 20);
+ this.kryptonLabel6.TabIndex = 12;
+ this.kryptonLabel6.Values.Text = "Sort Saved:";
+ //
+ // kryptonLabel5
+ //
+ this.kryptonLabel5.Location = new System.Drawing.Point(855, 12);
+ this.kryptonLabel5.Name = "kryptonLabel5";
+ this.kryptonLabel5.Size = new System.Drawing.Size(76, 20);
+ this.kryptonLabel5.TabIndex = 11;
+ this.kryptonLabel5.Values.Text = "Filter Saved:";
+ //
+ // kcmbSortSaved
+ //
+ this.kcmbSortSaved.DropDownWidth = 159;
+ this.kcmbSortSaved.IntegralHeight = false;
+ this.kcmbSortSaved.Location = new System.Drawing.Point(937, 39);
+ this.kcmbSortSaved.Name = "kcmbSortSaved";
+ this.kcmbSortSaved.Size = new System.Drawing.Size(159, 21);
+ this.kcmbSortSaved.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near;
+ this.kcmbSortSaved.TabIndex = 10;
+ //
+ // kcmbSavedFilters
+ //
+ this.kcmbSavedFilters.DropDownWidth = 159;
+ this.kcmbSavedFilters.IntegralHeight = false;
+ this.kcmbSavedFilters.Location = new System.Drawing.Point(937, 12);
+ this.kcmbSavedFilters.Name = "kcmbSavedFilters";
+ this.kcmbSavedFilters.Size = new System.Drawing.Size(159, 21);
+ this.kcmbSavedFilters.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near;
+ this.kcmbSavedFilters.TabIndex = 9;
+ //
+ // ktxtStringFilter
+ //
+ this.ktxtStringFilter.Location = new System.Drawing.Point(147, 159);
+ this.ktxtStringFilter.Name = "ktxtStringFilter";
+ this.ktxtStringFilter.Size = new System.Drawing.Size(100, 23);
+ this.ktxtStringFilter.TabIndex = 8;
+ this.ktxtStringFilter.TextChanged += new System.EventHandler(this.ktxtStringFilter_TextChanged);
+ //
+ // kryptonLabel4
+ //
+ this.kryptonLabel4.Location = new System.Drawing.Point(13, 159);
+ this.kryptonLabel4.Name = "kryptonLabel4";
+ this.kryptonLabel4.Size = new System.Drawing.Size(128, 20);
+ this.kryptonLabel4.TabIndex = 7;
+ this.kryptonLabel4.Values.Text = "Filter column \"string\":";
+ //
+ // ktxtSortString
+ //
+ this.ktxtSortString.Location = new System.Drawing.Point(207, 72);
+ this.ktxtSortString.Multiline = true;
+ this.ktxtSortString.Name = "ktxtSortString";
+ this.ktxtSortString.ReadOnly = true;
+ this.ktxtSortString.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.ktxtSortString.Size = new System.Drawing.Size(180, 80);
+ this.ktxtSortString.TabIndex = 6;
+ //
+ // kryptonLabel2
+ //
+ this.kryptonLabel2.Location = new System.Drawing.Point(207, 45);
+ this.kryptonLabel2.Name = "kryptonLabel2";
+ this.kryptonLabel2.Size = new System.Drawing.Size(71, 20);
+ this.kryptonLabel2.TabIndex = 5;
+ this.kryptonLabel2.Values.Text = "Sort String:";
+ //
+ // ktxtFilterString
+ //
+ this.ktxtFilterString.Location = new System.Drawing.Point(13, 72);
+ this.ktxtFilterString.Multiline = true;
+ this.ktxtFilterString.Name = "ktxtFilterString";
+ this.ktxtFilterString.ReadOnly = true;
+ this.ktxtFilterString.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.ktxtFilterString.Size = new System.Drawing.Size(180, 80);
+ this.ktxtFilterString.TabIndex = 4;
+ //
+ // kryptonLabel1
+ //
+ this.kryptonLabel1.Location = new System.Drawing.Point(13, 45);
+ this.kryptonLabel1.Name = "kryptonLabel1";
+ this.kryptonLabel1.Size = new System.Drawing.Size(76, 20);
+ this.kryptonLabel1.TabIndex = 3;
+ this.kryptonLabel1.Values.Text = "Filter String:";
+ //
+ // kcmbMemoryTest
+ //
+ this.kcmbMemoryTest.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.kcmbMemoryTest.DropDownWidth = 121;
+ this.kcmbMemoryTest.IntegralHeight = false;
+ this.kcmbMemoryTest.Location = new System.Drawing.Point(393, 13);
+ this.kcmbMemoryTest.Name = "kcmbMemoryTest";
+ this.kcmbMemoryTest.Size = new System.Drawing.Size(121, 21);
+ this.kcmbMemoryTest.StateCommon.ComboBox.Content.TextH = Krypton.Toolkit.PaletteRelativeAlign.Near;
+ this.kcmbMemoryTest.TabIndex = 2;
+ //
+ // kbtnMemoryTest
+ //
+ this.kbtnMemoryTest.Location = new System.Drawing.Point(207, 12);
+ this.kbtnMemoryTest.Name = "kbtnMemoryTest";
+ this.kbtnMemoryTest.Size = new System.Drawing.Size(180, 25);
+ this.kbtnMemoryTest.TabIndex = 1;
+ this.kbtnMemoryTest.Values.Text = "Memory Test";
+ this.kbtnMemoryTest.Click += new System.EventHandler(this.kbtnMemoryTest_Click);
+ //
+ // kbtnLoadRandomData
+ //
+ this.kbtnLoadRandomData.Location = new System.Drawing.Point(13, 13);
+ this.kbtnLoadRandomData.Name = "kbtnLoadRandomData";
+ this.kbtnLoadRandomData.Size = new System.Drawing.Size(167, 25);
+ this.kbtnLoadRandomData.TabIndex = 0;
+ this.kbtnLoadRandomData.Values.Text = "Load &Random Data";
+ this.kbtnLoadRandomData.Click += new System.EventHandler(this.kbtnLoadRandomData_Click);
+ //
+ // kryptonPanel2
+ //
+ this.kryptonPanel2.Controls.Add(this.statusStrip1);
+ this.kryptonPanel2.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.kryptonPanel2.Location = new System.Drawing.Point(0, 622);
+ this.kryptonPanel2.Name = "kryptonPanel2";
+ this.kryptonPanel2.Size = new System.Drawing.Size(1108, 22);
+ this.kryptonPanel2.TabIndex = 1;
+ //
+ // statusStrip1
+ //
+ this.statusStrip1.Font = new System.Drawing.Font("Segoe UI", 9F);
+ this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsslMemoryUsage});
+ this.statusStrip1.Location = new System.Drawing.Point(0, 0);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.ManagerRenderMode;
+ this.statusStrip1.Size = new System.Drawing.Size(1108, 22);
+ this.statusStrip1.TabIndex = 0;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // tsslMemoryUsage
+ //
+ this.tsslMemoryUsage.Name = "tsslMemoryUsage";
+ this.tsslMemoryUsage.Size = new System.Drawing.Size(116, 17);
+ this.tsslMemoryUsage.Text = "Memory Usage: /Mb";
+ //
+ // kryptonPanel3
+ //
+ this.kryptonPanel3.Controls.Add(this.ktxtTotalRows);
+ this.kryptonPanel3.Controls.Add(this.kryptonLabel3);
+ this.kryptonPanel3.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.kryptonPanel3.Location = new System.Drawing.Point(0, 593);
+ this.kryptonPanel3.Name = "kryptonPanel3";
+ this.kryptonPanel3.Size = new System.Drawing.Size(1108, 29);
+ this.kryptonPanel3.TabIndex = 2;
+ //
+ // ktxtTotalRows
+ //
+ this.ktxtTotalRows.Location = new System.Drawing.Point(92, 3);
+ this.ktxtTotalRows.Name = "ktxtTotalRows";
+ this.ktxtTotalRows.Size = new System.Drawing.Size(100, 23);
+ this.ktxtTotalRows.TabIndex = 1;
+ //
+ // kryptonLabel3
+ //
+ this.kryptonLabel3.Location = new System.Drawing.Point(13, 6);
+ this.kryptonLabel3.Name = "kryptonLabel3";
+ this.kryptonLabel3.Size = new System.Drawing.Size(73, 20);
+ this.kryptonLabel3.TabIndex = 0;
+ this.kryptonLabel3.Values.Text = "Total Rows:";
+ //
+ // kryptonPanel4
+ //
+ this.kryptonPanel4.Controls.Add(this.kadgvMain);
+ this.kryptonPanel4.Controls.Add(this.kryptonAdvancedDataGridViewSearchToolBar1);
+ this.kryptonPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kryptonPanel4.Location = new System.Drawing.Point(0, 189);
+ this.kryptonPanel4.Name = "kryptonPanel4";
+ this.kryptonPanel4.Size = new System.Drawing.Size(1108, 404);
+ this.kryptonPanel4.TabIndex = 3;
+ //
+ // kadgvMain
+ //
+ this.kadgvMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.kadgvMain.FilterAndSortEnabled = true;
+ this.kadgvMain.FilterStringChangedInvokeBeforeDatasourceUpdate = true;
+ this.kadgvMain.Location = new System.Drawing.Point(0, 27);
+ this.kadgvMain.Name = "kadgvMain";
+ this.kadgvMain.Size = new System.Drawing.Size(1108, 377);
+ this.kadgvMain.SortStringChangedInvokeBeforeDatasourceUpdate = true;
+ this.kadgvMain.TabIndex = 1;
+ this.kadgvMain.SortStringChanged += new System.EventHandler(this.kadgvMain_SortStringChanged);
+ this.kadgvMain.FilterStringChanged += new System.EventHandler(this.kadgvMain_FilterStringChanged);
+ //
+ // kryptonAdvancedDataGridViewSearchToolBar1
+ //
+ this.kryptonAdvancedDataGridViewSearchToolBar1.AllowMerge = false;
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Font = new System.Drawing.Font("Segoe UI", 9F);
+ this.kryptonAdvancedDataGridViewSearchToolBar1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Location = new System.Drawing.Point(0, 0);
+ this.kryptonAdvancedDataGridViewSearchToolBar1.MaximumSize = new System.Drawing.Size(0, 27);
+ this.kryptonAdvancedDataGridViewSearchToolBar1.MinimumSize = new System.Drawing.Size(0, 27);
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Name = "kryptonAdvancedDataGridViewSearchToolBar1";
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Size = new System.Drawing.Size(1108, 27);
+ this.kryptonAdvancedDataGridViewSearchToolBar1.TabIndex = 0;
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Text = "kryptonAdvancedDataGridViewSearchToolBar1";
+ this.kryptonAdvancedDataGridViewSearchToolBar1.Search += new Krypton.Utilities.AdvancedDataGridViewSearchToolBarSearchEventHandler(this.kryptonAdvancedDataGridViewSearchToolBar1_Search);
+ //
+ // bsData
+ //
+ this.bsData.ListChanged += new System.ComponentModel.ListChangedEventHandler(this.bsData_ListChanged);
+ //
+ // AdvancedDataGridView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1108, 644);
+ this.Controls.Add(this.kryptonPanel4);
+ this.Controls.Add(this.kryptonPanel3);
+ this.Controls.Add(this.kryptonPanel2);
+ this.Controls.Add(this.kryptonPanel1);
+ this.Name = "AdvancedDataGridView";
+ this.Text = "AdvancedDataGridView";
+ this.Load += new System.EventHandler(this.AdvancedDataGridView_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel1)).EndInit();
+ this.kryptonPanel1.ResumeLayout(false);
+ this.kryptonPanel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbSortSaved)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbSavedFilters)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kcmbMemoryTest)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel2)).EndInit();
+ this.kryptonPanel2.ResumeLayout(false);
+ this.kryptonPanel2.PerformLayout();
+ this.statusStrip1.ResumeLayout(false);
+ this.statusStrip1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel3)).EndInit();
+ this.kryptonPanel3.ResumeLayout(false);
+ this.kryptonPanel3.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kryptonPanel4)).EndInit();
+ this.kryptonPanel4.ResumeLayout(false);
+ this.kryptonPanel4.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.kadgvMain)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.bsData)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private KryptonPanel kryptonPanel1;
+ private KryptonPanel kryptonPanel2;
+ private KryptonPanel kryptonPanel3;
+ private KryptonPanel kryptonPanel4;
+ private KryptonButton kbtnLoadRandomData;
+ private KryptonButton kbtnMemoryTest;
+ private KryptonComboBox kcmbMemoryTest;
+ private KryptonLabel kryptonLabel1;
+ private KryptonTextBox ktxtFilterString;
+ private KryptonTextBox ktxtSortString;
+ private KryptonLabel kryptonLabel2;
+ private Krypton.Utilities.KryptonAdvancedDataGridViewSearchToolBar kryptonAdvancedDataGridViewSearchToolBar1;
+ private Krypton.Utilities.KryptonAdvancedDataGridView kadgvMain;
+ private StatusStrip statusStrip1;
+ private ToolStripStatusLabel tsslMemoryUsage;
+ private KryptonLabel kryptonLabel3;
+ private KryptonTextBox ktxtTotalRows;
+ private KryptonLabel kryptonLabel4;
+ private KryptonTextBox ktxtStringFilter;
+ private KryptonLabel kryptonLabel5;
+ private KryptonComboBox kcmbSortSaved;
+ private KryptonComboBox kcmbSavedFilters;
+ private KryptonLabel kryptonLabel6;
+ private KryptonButton kbtnSaveFilters;
+ private KryptonButton kbtnClearFilters;
+ private KryptonButton kbtnApplySavedFilters;
+ private BindingSource bsData;
+ }
+}
\ No newline at end of file
diff --git a/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs
new file mode 100644
index 0000000000..d891365935
--- /dev/null
+++ b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.cs
@@ -0,0 +1,483 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using Krypton.Utilities;
+
+namespace TestForm
+{
+ public partial class AdvancedDataGridViewTest : KryptonForm
+ {
+ #region Instance Fields
+
+ private DataTable? _dataTable = null;
+ private DataSet? _dataSet = null;
+
+ private SortedDictionary _filtersaved = new SortedDictionary();
+ private SortedDictionary _sortsaved = new SortedDictionary();
+
+ private bool _testtranslations = false;
+ private bool _testtranslationsFromFile = false;
+
+ private static int DisplayItemsCounter = 100;
+
+ private static bool MemoryTestEnabled = true;
+ private const int MEMORY_TEST_NUM = 100;
+ private bool _memorytest = false;
+ private object[][] _inrows = new object[][] { };
+
+ private Timer? _memorytestclosetimer = null;
+ private Timer? _timermemoryusage = null;
+
+ private static bool CollectGarbageOnTimerMemoryUsageUpdate = true;
+
+ #endregion
+
+ #region Identity
+
+ public AdvancedDataGridViewTest()
+ {
+ InitializeComponent();
+
+ //set timers
+ if (components != null)
+ {
+ _memorytestclosetimer = new Timer(components)
+ {
+ Interval = 10
+ };
+ _timermemoryusage = new Timer(components)
+ {
+ Interval = 2000
+ };
+ }
+
+ //trigger the memory usage show
+ _timermemoryusage_Tick(null, null);
+
+ //set localization strings
+ Dictionary translations = new Dictionary();
+ foreach (KeyValuePair translation in KryptonAdvancedDataGridView.Translations)
+ {
+ if (!translations.ContainsKey(translation.Key))
+ {
+ translations.Add(translation.Key, $".{translation.Value}");
+ }
+ }
+ foreach (KeyValuePair translation in KryptonAdvancedDataGridViewSearchToolBar.Translations)
+ {
+ if (!translations.ContainsKey(translation.Key))
+ {
+ translations.Add(translation.Key, $".{translation.Value}");
+ }
+ }
+ if (_testtranslations)
+ {
+ KryptonAdvancedDataGridView.SetTranslations(translations);
+ KryptonAdvancedDataGridViewSearchToolBar.SetTranslations(translations);
+ }
+ if (_testtranslationsFromFile)
+ {
+ KryptonAdvancedDataGridView.SetTranslations(KryptonAdvancedDataGridView.LoadTranslationsFromFile("lang.json"));
+ KryptonAdvancedDataGridViewSearchToolBar.SetTranslations(KryptonAdvancedDataGridViewSearchToolBar.LoadTranslationsFromFile("lang.json"));
+ }
+
+ //set filter and sort saved
+ _filtersaved.Add(0, "");
+ _sortsaved.Add(0, "");
+ kcmbSavedFilters.DataSource = new BindingSource(_filtersaved, null!);
+ kcmbSavedFilters.DisplayMember = "Key";
+ kcmbSavedFilters.ValueMember = "Value";
+ kcmbSavedFilters.SelectedIndex = -1;
+ kcmbSortSaved.DataSource = new BindingSource(_sortsaved, null!);
+ kcmbSortSaved.DisplayMember = "Key";
+ kcmbSortSaved.ValueMember = "Value";
+ kcmbSortSaved.SelectedIndex = -1;
+
+ //set memory test button
+ kbtnMemoryTest.Enabled = MemoryTestEnabled;
+
+ //initialize dataset
+ _dataTable = new DataTable();
+ _dataSet = new DataSet();
+
+ //initialize bindingsource
+ bsData.DataSource = _dataSet;
+
+ //initialize datagridview
+ kadgvMain.SetDoubleBuffered();
+ kadgvMain.DataSource = bsData;
+
+ //set bindingsource
+ SetTestData();
+ }
+
+ public AdvancedDataGridViewTest(bool memoryTest, object[][] inRows) : this()
+ {
+ _memorytest = memoryTest;
+
+ _inrows = inRows;
+ }
+
+ #endregion
+
+ #region Implementation
+
+ ///
+ /// Loads a sample flag PNG from the output directory when present; otherwise builds a small solid-color placeholder
+ /// so the Advanced DataGridView image column demo runs without shipping binary assets.
+ ///
+ private static Image LoadOrCreateSampleFlag(string fileName, Color fallbackColor)
+ {
+ string path = Path.Combine(Application.StartupPath, fileName);
+ if (File.Exists(path))
+ {
+ return Image.FromFile(path);
+ }
+
+ var bmp = new Bitmap(24, 24);
+ using (Graphics g = Graphics.FromImage(bmp))
+ {
+ g.Clear(fallbackColor);
+ }
+
+ return bmp;
+ }
+
+ private void kbtnLoadRandomData_Click(object sender, EventArgs e)
+ {
+ //add test data to bindsource
+ AddTestData();
+ }
+
+ private void SetTestData()
+ {
+ _dataTable = _dataSet?.Tables.Add("TableTest");
+ if (_dataTable != null)
+ {
+ _dataTable.Columns.Add("int", typeof(int));
+ _dataTable.Columns.Add("decimal", typeof(decimal));
+ _dataTable.Columns.Add("double", typeof(double));
+ _dataTable.Columns.Add("date", typeof(DateTime));
+ _dataTable.Columns.Add("datetime", typeof(DateTime));
+ _dataTable.Columns.Add("string", typeof(string));
+ _dataTable.Columns.Add("boolean", typeof(bool));
+ _dataTable.Columns.Add("guid", typeof(Guid));
+ _dataTable.Columns.Add("image", typeof(Bitmap));
+ _dataTable.Columns.Add("timespan", typeof(TimeSpan));
+
+ bsData.DataMember = _dataTable.TableName;
+ }
+
+ kryptonAdvancedDataGridViewSearchToolBar1.SetColumns(kadgvMain.Columns);
+ }
+
+ private void AddTestData()
+ {
+ Random r = new Random();
+ Image[] sampleImages = new Image[2];
+ sampleImages[0] = LoadOrCreateSampleFlag("flag-green_24.png", Color.FromArgb(72, 170, 72));
+ sampleImages[1] = LoadOrCreateSampleFlag("flag-red_24.png", Color.FromArgb(210, 72, 72));
+
+ int maxMinutes = (int)((TimeSpan.FromHours(20) - TimeSpan.FromHours(10)).TotalMinutes);
+
+ if (_inrows.Length == 0)
+ {
+ for (int i = 0; i < DisplayItemsCounter; i++)
+ {
+ object[] newRow =
+ [
+ i,
+ Math.Round((decimal)i*2/3, 6),
+ Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6),
+ DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0).Date,
+ DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0),
+ (i*2 % 3 == 0 ? null : $"{i} str")!,
+ i % 2 == 0 ? true:false,
+ Guid.NewGuid(),
+ sampleImages[r.Next(0, 2)],
+ TimeSpan.FromHours(10).Add(TimeSpan.FromMinutes(r.Next(maxMinutes)))
+ ];
+
+ _dataTable?.Rows.Add(newRow);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < _inrows.Length; i++)
+ {
+ _dataTable?.Rows.Add(_inrows[i]);
+ }
+ }
+
+ }
+
+ private void AdvancedDataGridView_Load(object sender, EventArgs e)
+ {
+ //add test data to bindsource
+ AddTestData();
+
+ //setup datagridview
+ kadgvMain.SetFilterDateAndTimeEnabled(kadgvMain.Columns["datetime"], true);
+ kadgvMain.SetSortEnabled(kadgvMain.Columns["guid"], false);
+ kadgvMain.SetFilterChecklistEnabled(kadgvMain.Columns["guid"], false);
+ kadgvMain.SortAscending(kadgvMain.Columns["datetime"]);
+ kadgvMain.SortDescending(kadgvMain.Columns["double"]);
+ kadgvMain.SetTextFilterRemoveNodesOnSearch(kadgvMain.Columns["double"], false);
+ kadgvMain.SetChecklistTextFilterRemoveNodesOnSearchMode(kadgvMain.Columns["decimal"], false);
+ kadgvMain.SetFilterChecklistEnabled(kadgvMain.Columns["double"], false);
+ kadgvMain.SetFilterCustomEnabled(kadgvMain.Columns["timespan"], false);
+ kadgvMain.CleanSort(kadgvMain.Columns["datetime"]);
+ kadgvMain.SetFilterChecklistTextFilterTextChangedDelayNodes(kadgvMain.Columns["string"], 10);
+ kadgvMain.SetFilterChecklistTextFilterTextChangedDelayMs(kadgvMain.Columns["string"], 500);
+
+ //memory test
+ if (!_memorytest)
+ {
+ //set timer memory usage
+ _timermemoryusage?.Enabled = true;
+ _timermemoryusage?.Tick += _timermemoryusage_Tick;
+ }
+ else
+ {
+ kryptonPanel1.Visible = false;
+
+ _memorytestclosetimer?.Enabled = true;
+ _memorytestclosetimer?.Tick += _memorytestclosetimer_Tick;
+
+ foreach (DataGridViewColumn column in kadgvMain.Columns)
+ kadgvMain.ShowMenuStrip(column);
+ }
+ }
+
+ private void kadgvMain_FilterStringChanged(object sender, KryptonAdvancedDataGridView.FilterEventArgs e)
+ {
+ //eventually set the FilterString here
+ //if e.Cancel is set to true one have to update the datasource here using
+ //bindingSource_main.Filter = kadgvMain.FilterString;
+ //otherwise it will be updated by the component
+
+ //sample use of the override string filter
+ string stringColumnFilter = ktxtStringFilter.Text;
+ if (!string.IsNullOrEmpty(stringColumnFilter))
+ {
+ e.FilterString += (!string.IsNullOrEmpty(e.FilterString) ? " AND " : "") +
+ $"string LIKE '%{stringColumnFilter.Replace("'", "''")}%'";
+ }
+
+ ktxtFilterString.Text = e.FilterString;
+ }
+
+ private void kadgvMain_SortStringChanged(object sender, KryptonAdvancedDataGridView.SortEventArgs e)
+ {
+ //eventually set the SortString here
+ //if e.Cancel is set to true one have to update the datasource here
+ //bindingSource_main.Sort = kadgvMain.SortString;
+ //otherwise it will be updated by the component
+
+ ktxtSortString.Text = e.SortString;
+ }
+
+ private void ktxtStringFilter_TextChanged(object sender, EventArgs e)
+ {
+ //trigger the filter string changed function when text is changed
+ kadgvMain.TriggerFilterStringChanged();
+ }
+
+ private void bsData_ListChanged(object sender, ListChangedEventArgs e)
+ {
+ ktxtTotalRows.Text = bsData.List.Count.ToString();
+ }
+
+ private void kbtnSaveFilters_Click(object sender, EventArgs e)
+ {
+ _filtersaved.Add((kcmbSavedFilters.Items.Count - 1) + 1, kadgvMain.FilterString);
+ kcmbSavedFilters.DataSource = new BindingSource(_filtersaved, null!);
+ kcmbSavedFilters.SelectedIndex = kcmbSavedFilters.Items.Count - 1;
+ _sortsaved.Add((kcmbSortSaved.Items.Count - 1) + 1, kadgvMain.SortString);
+ kcmbSortSaved.DataSource = new BindingSource(_sortsaved, null!);
+ kcmbSortSaved.SelectedIndex = kcmbSortSaved.Items.Count - 1;
+ }
+
+ private void kbtnApplySavedFilters_Click(object sender, EventArgs e)
+ {
+ if (kcmbSavedFilters.SelectedIndex != -1 && kcmbSortSaved.SelectedIndex != -1)
+ {
+ kadgvMain.LoadFilterAndSort(kcmbSavedFilters.SelectedValue?.ToString(), kcmbSortSaved.SelectedValue?.ToString());
+ }
+ }
+
+ private void kbtnClearFilters_Click(object sender, EventArgs e)
+ {
+ kadgvMain.CleanFilterAndSort();
+ kcmbSavedFilters.SelectedIndex = -1;
+ kcmbSortSaved.SelectedIndex = -1;
+ }
+
+ private void kryptonAdvancedDataGridViewSearchToolBar1_Search(object sender, AdvancedDataGridViewSearchToolBarSearchEventArgs e)
+ {
+ bool restartSearch = true;
+ int startColumn = 0;
+ int startRow = 0;
+ if (!e.FromBegin)
+ {
+ bool endColumn = kadgvMain.CurrentCell != null && kadgvMain.CurrentCell.ColumnIndex + 1 >= kadgvMain.ColumnCount;
+ bool endRow = kadgvMain.CurrentCell != null && kadgvMain.CurrentCell.RowIndex + 1 >= kadgvMain.RowCount;
+
+ if (endColumn && endRow)
+ {
+ if (kadgvMain.CurrentCell != null)
+ {
+ startColumn = kadgvMain.CurrentCell.ColumnIndex;
+ startRow = kadgvMain.CurrentCell.RowIndex;
+ }
+ }
+ else
+ {
+ if (kadgvMain.CurrentCell != null)
+ {
+ startColumn = endColumn ? 0 : kadgvMain.CurrentCell.ColumnIndex + 1;
+ startRow = kadgvMain.CurrentCell.RowIndex + (endColumn ? 1 : 0);
+ }
+ }
+ }
+ DataGridViewCell? c = kadgvMain.FindCell(
+ e.ValueToSearch,
+ e.ColumnToSearch != null ? e.ColumnToSearch.Name : null,
+ startRow,
+ startColumn,
+ e.WholeWord,
+ e.CaseSensitive);
+ if (c == null && restartSearch)
+ {
+ c = kadgvMain.FindCell(
+ e.ValueToSearch,
+ e.ColumnToSearch != null ? e.ColumnToSearch.Name : null,
+ 0,
+ 0,
+ e.WholeWord,
+ e.CaseSensitive);
+ }
+
+ if (c != null)
+ {
+ kadgvMain.CurrentCell = c;
+ }
+ }
+
+ private void _timermemoryusage_Tick(object? sender, EventArgs? e)
+ {
+ if (CollectGarbageOnTimerMemoryUsageUpdate)
+ {
+ GC.Collect();
+ }
+
+ tsslMemoryUsage.Text = $@"Memory Usage: {GC.GetTotalMemory(false) / (1024 * 1024)}Mb";
+ }
+
+ private void kbtnMemoryTest_Click(object sender, EventArgs e)
+ {
+ if (kcmbMemoryTest.SelectedItem != null && kcmbMemoryTest.SelectedItem.ToString() == "FullForm")
+ {
+ //build random data
+ Random r = new Random();
+ Image[] sampleimages = new Image[2];
+ sampleimages[0] = LoadOrCreateSampleFlag("flag-green_24.png", Color.FromArgb(72, 170, 72));
+ sampleimages[1] = LoadOrCreateSampleFlag("flag-red_24.png", Color.FromArgb(210, 72, 72));
+ int maxMinutes = (int)((TimeSpan.FromHours(20) - TimeSpan.FromHours(10)).TotalMinutes);
+ object[][] testrows = new object[100][];
+ for (int i = 0; i < 100; i++)
+ {
+ object[] newrow = new object[] {
+ i,
+ Math.Round((decimal)i*2/3, 6),
+ Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6),
+ DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0).Date,
+ DateTime.Today.AddHours(i*2).AddHours(i%2 == 0 ?i*10+1:0).AddMinutes(i%2 == 0 ?i*10+1:0).AddSeconds(i%2 == 0 ?i*10+1:0).AddMilliseconds(i%2 == 0 ?i*10+1:0),
+ (i*2 % 3 == 0 ? null : $"{i} str")!,
+ i % 2 == 0 ? true:false,
+ Guid.NewGuid(),
+ sampleimages[r.Next(0, 2)],
+ TimeSpan.FromHours(10).Add(TimeSpan.FromMinutes(r.Next(maxMinutes)))
+ };
+
+ testrows.SetValue(newrow, i);
+ }
+
+ //show the forms
+ for (int i = 0; i < MEMORY_TEST_NUM; i++)
+ {
+ AdvancedDataGridViewTest formtest = new AdvancedDataGridViewTest(true, testrows);
+ formtest.Show();
+ //wait for the form to be disposed
+ while (!formtest.IsDisposed)
+ {
+ Application.DoEvents();
+ System.Threading.Thread.Sleep(100);
+ }
+ }
+ }
+ else if (kcmbMemoryTest.SelectedItem != null && kcmbMemoryTest.SelectedItem.ToString() == "DataSource")
+ {
+ object? datasourcePrev = kadgvMain.DataSource;
+
+ //initialize dataset
+ DataTable dataTableTest = new DataTable();
+ DataSet dataSetTest = new DataSet();
+ dataTableTest = dataSetTest.Tables.Add("TableTest");
+ dataTableTest.Columns.Add("int", typeof(int));
+ dataTableTest.Columns.Add("decimal", typeof(decimal));
+ dataTableTest.Columns.Add("double", typeof(double));
+ //add data
+ for (int i = 0; i < 100; i++)
+ {
+ object[] newrow = new object[] {
+ i,
+ Math.Round((decimal)i*2/3, 6),
+ Math.Round(i % 2 == 0 ? (double)i*2/3 : (double)i/2, 6)
+ };
+ dataTableTest.Rows.Add(newrow);
+ }
+
+ //update the DataSource
+ for (int i = 0; i < MEMORY_TEST_NUM; i++)
+ {
+ using (BindingSource bindingSourceTest = new BindingSource())
+ {
+ bindingSourceTest.DataSource = dataSetTest;
+ bindingSourceTest.DataMember = dataTableTest.TableName;
+ kadgvMain.DataSource = null;
+ kadgvMain.ColumnHeadersVisible = false;
+ kadgvMain.DataSource = bindingSourceTest;
+ kadgvMain.Refresh();
+ kadgvMain.ColumnHeadersVisible = true;
+ Application.DoEvents();
+ }
+ }
+
+ //restore original datasource
+ kadgvMain.DataSource = datasourcePrev;
+ }
+ else
+ {
+ KryptonMessageBox.Show("Select a Memory Test", "Warning", KryptonMessageBoxButtons.OK, KryptonMessageBoxIcon.Warning);
+ }
+ }
+
+ private void _memorytestclosetimer_Tick(object? sender, EventArgs e)
+ {
+ _dataTable?.Rows.Clear();
+
+ Close();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx
new file mode 100644
index 0000000000..1af7de150c
--- /dev/null
+++ b/Source/Krypton Components/TestForm/AdvancedDataGridViewTest.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Source/Krypton Components/TestForm/StartScreen.cs b/Source/Krypton Components/TestForm/StartScreen.cs
index 66f126cadf..2181209a1f 100644
--- a/Source/Krypton Components/TestForm/StartScreen.cs
+++ b/Source/Krypton Components/TestForm/StartScreen.cs
@@ -57,6 +57,7 @@ public StartScreen()
///
private void AddButtons()
{
+ CreateButton("KryptonAdvancedDataGridView", "Need to manipulate some data?");
CreateButton("AboutBox", "Try this About Box for a change");
CreateButton("Accessibility Test (UIA Providers)", "Comprehensive demo and test for UIA Provider implementation (Issue #762). Tests all 10 controls with accessibility support, organized by category with detailed results.");
CreateButton("Badge Test", "Comprehensive badge functionality demonstration for KryptonButton and KryptonCheckButton.");
diff --git a/Source/Krypton Components/TestForm/flag-green_24.png b/Source/Krypton Components/TestForm/flag-green_24.png
new file mode 100644
index 0000000000..31a4a705d0
Binary files /dev/null and b/Source/Krypton Components/TestForm/flag-green_24.png differ
diff --git a/Source/Krypton Components/TestForm/flag-red_24.png b/Source/Krypton Components/TestForm/flag-red_24.png
new file mode 100644
index 0000000000..6e9368edac
Binary files /dev/null and b/Source/Krypton Components/TestForm/flag-red_24.png differ