Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cell using 'DisplayMember' to find and set value resulting in setting bad value. #11311

Open
bukowa opened this issue May 3, 2024 · 8 comments
Assignees
Labels
Milestone

Comments

@bukowa
Copy link

bukowa commented May 3, 2024

.NET version

$ dotnet --info
.NET SDK:
 Version:           8.0.101   
 Commit:            6eceda187b
 Workload version:  8.0.100-manifests.30fce108

Did it work in .NET Framework?

Not tested/verified

Did it work in any of the earlier releases of .NET Core or .NET 5+?

No response

Issue description

I created very simple showcase here https://github.com/bukowa/Issue_WinForms_FormattedValue
As you can see if the DisplayMember returns the same value it will always be set to the first one.

Basically the value will be set to the first matching occurence of the DisplayMember found in the BindingList.
Animation

The code is here

private object? ItemFromComboBoxDataSource(PropertyDescriptor property, object key)

private bool LookupValue(object? formattedValue, out object? value)

Steps to reproduce

https://github.com/bukowa/Issue_WinForms_FormattedValue

@bukowa bukowa added the untriaged The team needs to look at this issue in the next triage label May 3, 2024
@elachlan
Copy link
Contributor

elachlan commented May 3, 2024

Maybe its the ItemComparer? It looks like its comparing based on the DisplayText.

public partial class DataGridViewComboBoxCell : DataGridViewCell
{
private sealed class ItemComparer : IComparer<object?>
{
private readonly DataGridViewComboBoxCell _dataGridViewComboBoxCell;
public ItemComparer(DataGridViewComboBoxCell dataGridViewComboBoxCell)
{
_dataGridViewComboBoxCell = dataGridViewComboBoxCell;
}
public int Compare(object? item1, object? item2)
{
if (IComparerHelpers.CompareReturnIfNull(item1, item2, out int? returnValue))
{
return (int)returnValue;
}
string? itemName1 = _dataGridViewComboBoxCell.GetItemDisplayText(item1);
string? itemName2 = _dataGridViewComboBoxCell.GetItemDisplayText(item2);
CompareInfo compInfo = Application.CurrentCulture.CompareInfo;
return compInfo.Compare(itemName1, itemName2, CompareOptions.StringSort);
}
}
}

@elachlan elachlan added 🪲 bug Product bug (most likely) area-Controls-DataGridView labels May 3, 2024
@elachlan
Copy link
Contributor

elachlan commented May 3, 2024

@Olina-Zhang can your team please test this to confirm?

@bukowa
Copy link
Author

bukowa commented May 4, 2024

Maybe its the ItemComparer? It looks like its comparing based on the DisplayText.

public partial class DataGridViewComboBoxCell : DataGridViewCell
{
private sealed class ItemComparer : IComparer<object?>
{
private readonly DataGridViewComboBoxCell _dataGridViewComboBoxCell;
public ItemComparer(DataGridViewComboBoxCell dataGridViewComboBoxCell)
{
_dataGridViewComboBoxCell = dataGridViewComboBoxCell;
}
public int Compare(object? item1, object? item2)
{
if (IComparerHelpers.CompareReturnIfNull(item1, item2, out int? returnValue))
{
return (int)returnValue;
}
string? itemName1 = _dataGridViewComboBoxCell.GetItemDisplayText(item1);
string? itemName2 = _dataGridViewComboBoxCell.GetItemDisplayText(item2);
CompareInfo compInfo = Application.CurrentCulture.CompareInfo;
return compInfo.Compare(itemName1, itemName2, CompareOptions.StringSort);
}
}
}

I tried setting breakpoint at this method and it was never executed.
Upgraded to

$ dotnet --info
.NET SDK:
 Version:           8.0.204
 Commit:            c338c7548c
 Workload version:  8.0.200-manifests.7d36c14f

@MelonWang1
Copy link
Contributor

MelonWang1 commented May 6, 2024

@elachlan This issue also repro's in .NET9.0/8.0/7.0/6.0/5.0/3.1 and .NET framework app.

11311.mp4

@alandryz83
Copy link

alandryz83 commented May 6, 2024 via email

@LeafShi1
Copy link
Member

LeafShi1 commented May 7, 2024

The stack trace when switching Kitten name:

        System.Windows.Forms.dll!System.Windows.Forms.ComboBox.RefreshItems() Line 3142	C#
 	System.Windows.Forms.dll!System.Windows.Forms.ComboBox.OnDisplayMemberChanged(System.EventArgs e) Line 2963	C#
 	System.Windows.Forms.dll!System.Windows.Forms.ListControl.SetDataConnection(object newDataSource, System.Windows.Forms.BindingMemberInfo newDisplayMember, bool force) Line 741	C#
 	System.Windows.Forms.dll!System.Windows.Forms.ListControl.DisplayMember.set(string value) Line 114	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewComboBoxCell.InitializeEditingControl(int rowIndex, object initialFormattedValue, System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle) Line 1397	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.InitializeEditingControlValue(ref System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle, System.Windows.Forms.DataGridViewCell dataGridViewCell) Line 10130	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.RefreshEdit() Line 25940	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(System.ComponentModel.ListChangedEventArgs e) Line 651	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) Line 350	C#
 	System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.OnListChanged(System.ComponentModel.ListChangedEventArgs e) Line 911	C#
 	System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.List_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) Line 812	C#
 	System.ComponentModel.TypeConverter.dll!System.ComponentModel.BindingList<ScratchProject.Human>.Child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) Line 441	C#
 	ScratchProject.dll!ScratchProject.Human.OnPropertyChanged(string propertyName) Line 34	C#
 	ScratchProject.dll!ScratchProject.Human.Kitten.set(ScratchProject.Kitten value) Line 21	C#

Click on KittenId column:

>	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewComboBoxCell.GetFormattedValue(object value, int rowIndex, ref System.Windows.Forms.DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, System.Windows.Forms.DataGridViewDataErrorContexts context) Line 1088	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewCell.GetEditedFormattedValue(object value, int rowIndex, ref System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle, System.Windows.Forms.DataGridViewDataErrorContexts context) Line 1547	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewCell.PaintWork(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, System.Windows.Forms.DataGridViewElementStates cellState, System.Windows.Forms.DataGridViewCellStyle cellStyle, System.Windows.Forms.DataGridViewAdvancedBorderStyle advancedBorderStyle, System.Windows.Forms.DataGridViewPaintParts paintParts) Line 3681	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.PaintCells(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle rowBounds, int rowIndex, System.Windows.Forms.DataGridViewElementStates rowState, bool isFirstDisplayedRow, bool isLastVisibleRow, System.Windows.Forms.DataGridViewPaintParts paintParts) Line 1657	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridViewRow.Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle rowBounds, int rowIndex, System.Windows.Forms.DataGridViewElementStates rowState, bool isFirstDisplayedRow, bool isLastVisibleRow) Line 1469	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.PaintRows(System.Drawing.Graphics g, System.Drawing.Rectangle boundingRect, System.Drawing.Rectangle clipRect, bool singleHorizontalBorderAdded) Line 20086	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.PaintGrid(System.Drawing.Graphics g, System.Drawing.Rectangle gridBounds, System.Drawing.Rectangle clipRect, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded) Line 19968	C#
 	System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnPaint(System.Windows.Forms.PaintEventArgs e) Line 17092	C#
 	System.Windows.Forms.dll!System.Windows.Forms.Control.PaintWithErrorHandling(System.Windows.Forms.PaintEventArgs e, short layer) Line 8621	C#

@merriemcgaw merriemcgaw removed the untriaged The team needs to look at this issue in the next triage label May 15, 2024
@merriemcgaw merriemcgaw added this to the Future milestone May 15, 2024
@merriemcgaw
Copy link
Member

Assigning this to @KlausLoeffelmann to evaluate. That said, this may not meet the bar for .NET if it works the same way in .NET Framework. We'll let you know.

@bukowa
Copy link
Author

bukowa commented May 17, 2024

Assigning this to @KlausLoeffelmann to evaluate. That said, this may not meet the bar for .NET if it works the same way in .NET Framework. We'll let you know.

Hey and thanks. Looking forward to any information maybe there's some simple workaround?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants