Skip to content

Commit

Permalink
Merge pull request #1995 from giduac/1784-V95-KryptonDataGridView-reo…
Browse files Browse the repository at this point in the history
…rders-Columns-during-debugging

1784-V95-KryptonDataGridView-reorders-Columns-during-debugging
  • Loading branch information
PWagner1 authored Dec 26, 2024
2 parents 393214c + 7ef8f5a commit 3d4cecc
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 75 deletions.
1 change: 1 addition & 0 deletions Documents/Changelog/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
=======

## 2025-02-01 - Build 2502 (Version 95 - Patch 1) - February 2025
* Resolved [#1784](https://github.com/Krypton-Suite/Standard-Toolkit/issues/1784), `KryptonDataGridView` Auto generation of columns is not serialized correctly.
* Resolved [#1964](https://github.com/Krypton-Suite/Standard-Toolkit/issues/1964), `KryptonTreeView` Node crosses are not Dpi Scaled
* Resolved [#560](https://github.com/Krypton-Suite/Standard-Toolkit/issues/560), CheckBox Images are not scaled with dpi Awareness
* Resolved [#565](https://github.com/Krypton-Suite/Standard-Toolkit/issues/565), GroupBox icons are not scaled for dpi awareness
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ namespace Krypton.Toolkit
/// </summary>
[ToolboxItem(true)]
[ToolboxBitmap(typeof(KryptonDataGridView), "ToolboxBitmaps.KryptonDataGridView.bmp")]
[DesignerCategory(@"code")]
[Designer(typeof(KryptonDataGridViewDesigner))]
[DesignerCategory(@"Code")]
//[Designer(typeof(KryptonDataGridViewDesigner))] do not use for now. use the the winforms editor
[Designer($"System.Windows.Forms.Design.DataGridViewDesigner")]
[DefaultEvent(nameof(CellContentClick))]
[ComplexBindingProperties(nameof(DataSource), nameof(DataMember))]
[Docking(DockingBehavior.Ask)]
[Description(@"Display rows and columns of data of a grid you can customize.")]
public class KryptonDataGridView : DataGridView
{
Expand Down Expand Up @@ -350,13 +354,12 @@ protected override void Dispose(bool disposing)
#endregion

#region Public
[Browsable(false)]
[Description(@"When true and AutoGenerateColumns is true the KryptonDataGridView will use Krypton column types, when false the standard WinForms column types.")]
[Browsable(true)]
[Category(@"Behavior")]
[Description(@"When true the KryptonDataGridView will, upon connecting a data source, convert WinForms column types to Krypton column types, when false the standard WinForms column types.")]
[DefaultValue(true)]
public bool AutoGenerateKryptonColumns
{
get;
set;
public bool AutoGenerateKryptonColumns {
get; set;
} = true;

/// <summary>Gets or sets the <see cref="T:System.Windows.Forms.ContextMenuStrip" /> associated with this control.</summary>
Expand Down Expand Up @@ -1009,55 +1012,12 @@ protected virtual void OnButtonSpecChanged(object? sender, [DisallowNull] EventA


#region Protected Override
/// <inheritdoc/>
protected override void OnDataMemberChanged(EventArgs e)
{
base.OnDataMemberChanged(e);

if (AutoGenerateColumns
&& AutoGenerateKryptonColumns
&& DataSource is not null)
{
ReplaceDefaultColumsWithKryptonColumns();
}
}

/// <inheritdoc/>
protected override void OnDataSourceChanged(EventArgs e)
{
base.OnDataSourceChanged(e);

if (AutoGenerateColumns
&& AutoGenerateKryptonColumns
&& DataSource is not null)
{
ReplaceDefaultColumsWithKryptonColumns();
}
}

/// <inheritdoc/>
protected override void OnAutoGenerateColumnsChanged(EventArgs e)
{
// First handle the base the event
base.OnAutoGenerateColumnsChanged(e);

// If needed convert the winforms columns to Krypton columns
if (AutoGenerateColumns
&& AutoGenerateKryptonColumns
&& DataSource is not null)
{
ReplaceDefaultColumsWithKryptonColumns();
}
}

/// <inheritdoc/>
protected override void OnDataBindingComplete(DataGridViewBindingCompleteEventArgs e)
{
base.OnDataBindingComplete(e);

if (AutoGenerateColumns
&& AutoGenerateKryptonColumns
&& DataSource is not null)
if (AutoGenerateKryptonColumns && DataSource is not null)
{
ReplaceDefaultColumsWithKryptonColumns();
}
Expand Down Expand Up @@ -1719,44 +1679,62 @@ internal bool RightToLeftInternal
private void ReplaceDefaultColumsWithKryptonColumns()
{
DataGridViewColumn currentColumn;
KryptonDataGridViewTextBoxColumn newColumn;
List<int> columnsProcessed = [];
int index;
IComponentChangeService? changeService = null;
IDesignerHost? designerHost = null;

for (int i = 0 ; i < ColumnCount ; i++)
if (this.DesignMode)
{
changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
designerHost = this.Site!.GetService(typeof(IDesignerHost)) as IDesignerHost;
changeService?.OnComponentChanging(this, null);
}

for (int i = 0; i < ColumnCount; i++)
{
currentColumn = Columns[i];

/*
* Auto generated columns are always of type System.Windows.Forms.DataGridViewTextBoxColumn.
* Only columns that are of type DataGridViewTextBoxColumn and have the DataPropertyName set will be converted to krypton Columns.
*/
if (currentColumn is DataGridViewTextBoxColumn && currentColumn.DataPropertyName.Length > 0)
{
index = currentColumn.Index;
columnsProcessed.Add(index);

newColumn = new KryptonDataGridViewTextBoxColumn
{
Name = currentColumn.Name,
DataPropertyName = currentColumn.DataPropertyName,
HeaderText = currentColumn.HeaderText,
Width = currentColumn.Width
};
var newColumn = this.DesignMode
? designerHost?.CreateComponent(typeof(KryptonDataGridViewTextBoxColumn)) as KryptonDataGridViewTextBoxColumn
: new KryptonDataGridViewTextBoxColumn();

newColumn!.Name = currentColumn.Name;
newColumn.DataPropertyName = currentColumn.DataPropertyName;
newColumn.HeaderText = currentColumn.HeaderText;
newColumn.Width = currentColumn.Width;
newColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;

Columns.RemoveAt(index);
Columns.Insert(index, newColumn);

designerHost?.DestroyComponent(currentColumn);
}
}
else if (currentColumn is DataGridViewCheckBoxColumn && currentColumn.DataPropertyName.Length > 0)
{
index = currentColumn.Index;

/*
* After the columns have been replaced they need a little help so they have the same width as when only Winforms columns would've been auto added.
* Setting this value in the above for loop does not work.
*/
for (int i = 0 ; i < columnsProcessed.Count ; i++)
{
Columns[columnsProcessed[i]].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
var newColumn = this.DesignMode
? designerHost?.CreateComponent(typeof(KryptonDataGridViewCheckBoxColumn)) as KryptonDataGridViewCheckBoxColumn
: new KryptonDataGridViewCheckBoxColumn();

newColumn!.Name = currentColumn.Name;
newColumn.DataPropertyName = currentColumn.DataPropertyName;
newColumn.HeaderText = currentColumn.HeaderText;
newColumn.Width = currentColumn.Width;
newColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;

Columns.RemoveAt(index);
Columns.Insert(index, newColumn);

designerHost?.DestroyComponent(currentColumn);
}
}

changeService?.OnComponentChanged(this, null, null, null);
}

private void SetupVisuals()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#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 et al. 2017 - 2025. All rights reserved.
*
*/
#endregion

namespace Krypton.Toolkit
{
/// <summary>
/// This class is used within advanved columns that make use of embedded controls.
/// </summary>
[ToolboxItem(false)]
internal class KryptonDataGridViewCellIndicatorImage : IDisposable
{
#region Fields
// Cell indicator image
private Image? _image = null;
// Size of the image which is always square
private int _size;
// Datagridview the column belongs to.
private KryptonDataGridView? _dataGridView;
// State of disposal
private bool _disposed = false;

// type and state of the image
private PaletteRibbonGalleryButton _paletteRibbonGalleryButton = PaletteRibbonGalleryButton.Down;
private PaletteState _paletteState = PaletteState.Normal;
#endregion Fields

#region Identity
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="imageSize">The image size in pixels. Which will always be used to square the image. Default is 14.</param>
public KryptonDataGridViewCellIndicatorImage(int imageSize = 14)
{
_size = imageSize;

UpdateCellIndicatorImage(true);
KryptonManager.GlobalPaletteChanged += OnKryptonManagerGlobalPaletteChanged;
}
#endregion Identity

#region Public
/// <summary>
/// Reference to the column's DataGridView.<br/>
/// Set this property via the column's 'protected override void OnDataGridViewChanged()'.
/// </summary>
public KryptonDataGridView? DataGridView
{
get => _dataGridView;

set
{
if (_dataGridView != value)
{
if (_dataGridView is not null)
{
_dataGridView.PaletteChanged -= OnDataGridViewPaletteChanged;
}

_dataGridView = value;

if (_dataGridView is not null)
{
_dataGridView.PaletteChanged += OnDataGridViewPaletteChanged;
UpdateCellIndicatorImage(false);
}
}
}
}

/// <summary>
/// Cell indicator image.
/// </summary>
public virtual Image? Image => _image;

/// <inheritdoc/>>
public void Dispose()
{
Dispose(true);
}

/// <inheritdoc cref="Dispose()"/>
public void Dispose(bool disposing)
{
// If the column is disposed at runtime the eventhandlers need to unsubscribe from the grid and kmananger
try
{
if (!_disposed && disposing)
{
// Since the DataGridView property is controlled internally,
// use the cached reference to unsubscribe from the event
if (_dataGridView is not null)
{
_dataGridView.PaletteChanged -= OnDataGridViewPaletteChanged;
}

KryptonManager.GlobalPaletteChanged -= OnKryptonManagerGlobalPaletteChanged;
_dataGridView = null;

_disposed = true;
}
}
catch { }
}
#endregion Public

#region Private
/// <summary>
/// Subscribe this handler to: KryptonDataGridView.PaletteChanged
/// </summary>
/// <param name="sender">Not used.</param>
/// <param name="e">Not used.</param>
private void OnDataGridViewPaletteChanged(object? sender, EventArgs e) => UpdateCellIndicatorImage(false);

/// <summary>
/// Subscribe this handler to: KryptonManager.GlobalPaletteChanged
/// </summary>
/// <param name="sender">Not used.</param>
/// <param name="e">Not used.</param>
private void OnKryptonManagerGlobalPaletteChanged(object? sender, EventArgs e) => UpdateCellIndicatorImage(true);

/// <summary>
/// Updates the cell indicator image based on the source from where the theme change originated.
/// </summary>
/// <param name="updateFromKryptonManager">True if KryptonManager fired the theme change, otherwise from KryptonDataGridView.</param>
private void UpdateCellIndicatorImage(bool updateFromKryptonManager)
{
if (updateFromKryptonManager)
{
// Probably the case used most, so first to check.
_image = KryptonManager.CurrentGlobalPalette.GetGalleryButtonImage(_paletteRibbonGalleryButton, _paletteState)!;
ResizeCellIndicatorImage();
}
else if (DataGridView is KryptonDataGridView dataGridView)
{
if (dataGridView.Palette is not null && dataGridView.PaletteMode == PaletteMode.Custom)
{
// The grid has a custom palette instance assigned to it and PaletteMode is Custom
_image = dataGridView.Palette.GetGalleryButtonImage(_paletteRibbonGalleryButton, _paletteState);
}
else
{
// Fetch through KryptonManager using the locally set palette mode
_image = KryptonManager
.GetPaletteForMode(dataGridView.PaletteMode)
.GetGalleryButtonImage(_paletteRibbonGalleryButton, _paletteState)!;
}

ResizeCellIndicatorImage();
}
}

/// <summary>
/// This method may only be used by UpdateCellIndicatorImage()
/// </summary>
private void ResizeCellIndicatorImage()
{
if (_image is not null && (_image.Width != _size || _image.Height != _size))
{
_image = new Bitmap(_image, _size, _size);
}
}
#endregion Private
}
}
Loading

0 comments on commit 3d4cecc

Please sign in to comment.