Skip to content

Commit 7d96dbd

Browse files
[release/9.0] fix #13071 Changing properties with RefreshProperties.All does not requery the property list in the PropertyGrid in .net 9 (worked in .net 8) (#13356)
Backport of [#13295](#13295) to release/9.0 Fixes #13071 ## Proposed changes - - revert [PR#12431](#12431) , use another approach to fix [Issue#12440](#12440) - Introduce `EditMouseDown` flag in PropertyGridView.flag. This flag is on when the TextBox in the PropertyGrid.GridEntry is focused and is off when editing is done. - The cause of [Issue#12440](#12440) is that after editing is done, GridEntryAccessibleObject will raise AutomationFocusChangedEvent GridEntry.GridEntryAccessibleObject.cs ``` c# ... internal override void SetFocus() { if (PropertyGridView is null || !PropertyGridView.IsHandleCreated) { return; } base.SetFocus(); RaiseAutomationEvent(UIA_EVENT_ID.UIA_AutomationFocusChangedEventId); } ``` So in order to not let TextBox loose rectangle, add conditions to that event to exclude two cases: 1. when InPropertySet is on 2. when EditMouseDown is on ## Regression? - Yes <!-- ## Customer Impact - - ## Risk - --> ## Screenshots <!-- Remove this section if PR does not change UI --> ### Before GetProperties method didn't get invoked described in [#13071](#13071) ### After https://github.com/user-attachments/assets/4d013d27-8ebc-4020-a977-d2f825280bfc https://github.com/user-attachments/assets/7885c561-f37f-45fd-971c-6af9686db030 ## Test methodology <!-- How did you ensure quality? --> - - manually - <!-- ## Accessibility testing -->
2 parents 45fbdc1 + 906f2b7 commit 7d96dbd

File tree

4 files changed

+106
-30
lines changed

4 files changed

+106
-30
lines changed

src/System.Windows.Forms/src/System/Windows/Forms/Controls/PropertyGrid/PropertyGridInternal/GridEntry.GridEntryAccessibleObject.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,10 @@ internal override void SetFocus()
410410

411411
base.SetFocus();
412412

413-
RaiseAutomationEvent(UIA_EVENT_ID.UIA_AutomationFocusChangedEventId);
413+
if (!PropertyGridView.InPropertySet && !PropertyGridView.EditMouseDown)
414+
{
415+
RaiseAutomationEvent(UIA_EVENT_ID.UIA_AutomationFocusChangedEventId);
416+
}
414417
}
415418
}
416419
}

src/System.Windows.Forms/src/System/Windows/Forms/Controls/PropertyGrid/PropertyGridInternal/PropertyGridView.Flags.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ private enum Flags : ushort
2222
/// </summary>
2323
ButtonLaunchedEditor = 0x0100,
2424
NoDefault = 0x0200,
25-
ResizableDropDown = 0x0400
25+
ResizableDropDown = 0x0400,
26+
EditMouseDown = 0x0800
2627
}
2728
}

src/System.Windows.Forms/src/System/Windows/Forms/Controls/PropertyGrid/PropertyGridInternal/PropertyGridView.cs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,44 +2566,59 @@ private void OnEditLostFocus(object? sender, EventArgs e)
25662566
InvokeLostFocus(this, EventArgs.Empty);
25672567
}
25682568

2569-
private void OnEditMouseDown(object? sender, MouseEventArgs e)
2569+
internal bool EditMouseDown
25702570
{
2571-
if (!FocusInside)
2572-
{
2573-
SelectGridEntry(_selectedGridEntry, pageIn: false);
2574-
}
2575-
2576-
if (e.Clicks % 2 == 0)
2577-
{
2578-
DoubleClickRow(_selectedRow, toggleExpand: false, RowValue);
2579-
EditTextBox.SelectAll();
2580-
}
2571+
get => _flags.HasFlag(Flags.EditMouseDown);
2572+
private set => SetFlag(Flags.EditMouseDown, value);
2573+
}
25812574

2582-
if (_rowSelectTime == 0)
2575+
private void OnEditMouseDown(object? sender, MouseEventArgs e)
2576+
{
2577+
try
25832578
{
2584-
return;
2585-
}
2586-
2587-
// Check if the click happened within the double click time since the row was selected.
2588-
// This allows the edits to be selected with two clicks instead of 3 (select row, double click).
2589-
long timeStamp = DateTime.Now.Ticks;
2590-
int delta = (int)((timeStamp - _rowSelectTime) / 10000); // make it milliseconds
2579+
EditMouseDown = true;
25912580

2592-
if (delta < SystemInformation.DoubleClickTime)
2593-
{
2594-
Point screenPoint = EditTextBox.PointToScreen(e.Location);
2581+
if (!FocusInside)
2582+
{
2583+
SelectGridEntry(_selectedGridEntry, pageIn: false);
2584+
}
25952585

2596-
if (Math.Abs(screenPoint.X - _rowSelectPos.X) < SystemInformation.DoubleClickSize.Width &&
2597-
Math.Abs(screenPoint.Y - _rowSelectPos.Y) < SystemInformation.DoubleClickSize.Height)
2586+
if (e.Clicks % 2 == 0)
25982587
{
25992588
DoubleClickRow(_selectedRow, toggleExpand: false, RowValue);
2600-
PInvoke.SendMessage(EditTextBox, PInvoke.WM_LBUTTONUP, (WPARAM)0, (LPARAM)e.Location);
26012589
EditTextBox.SelectAll();
26022590
}
26032591

2604-
_rowSelectPos = Point.Empty;
2592+
if (_rowSelectTime == 0)
2593+
{
2594+
return;
2595+
}
26052596

2606-
_rowSelectTime = 0;
2597+
// Check if the click happened within the double click time since the row was selected.
2598+
// This allows the edits to be selected with two clicks instead of 3 (select row, double click).
2599+
long timeStamp = DateTime.Now.Ticks;
2600+
int delta = (int)((timeStamp - _rowSelectTime) / 10000); // make it milliseconds
2601+
2602+
if (delta < SystemInformation.DoubleClickTime)
2603+
{
2604+
Point screenPoint = EditTextBox.PointToScreen(e.Location);
2605+
2606+
if (Math.Abs(screenPoint.X - _rowSelectPos.X) < SystemInformation.DoubleClickSize.Width &&
2607+
Math.Abs(screenPoint.Y - _rowSelectPos.Y) < SystemInformation.DoubleClickSize.Height)
2608+
{
2609+
DoubleClickRow(_selectedRow, toggleExpand: false, RowValue);
2610+
PInvoke.SendMessage(EditTextBox, PInvoke.WM_LBUTTONUP, (WPARAM)0, (LPARAM)e.Location);
2611+
EditTextBox.SelectAll();
2612+
}
2613+
2614+
_rowSelectPos = Point.Empty;
2615+
2616+
_rowSelectTime = 0;
2617+
}
2618+
}
2619+
finally
2620+
{
2621+
EditMouseDown = false;
26072622
}
26082623
}
26092624

@@ -3998,7 +4013,7 @@ private void Refresh(bool fullRefresh, int startRow, int endRow)
39984013
startRow = 0;
39994014
}
40004015

4001-
if (OwnerGrid.HavePropertyEntriesChanged())
4016+
if (fullRefresh || OwnerGrid.HavePropertyEntriesChanged())
40024017
{
40034018
if (HasEntries && !InPropertySet && !CommitEditTextBox())
40044019
{

src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/PropertyGridTests.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4122,6 +4122,63 @@ public void PropertyGrid_SelectedGridItemChanged_TriggeredCorrectly()
41224122
eventArgs.NewSelection.Should().Be(gridItem);
41234123
}
41244124

4125+
// Regression test for https://github.com/dotnet/winforms/issues/13071
4126+
[WinFormsFact]
4127+
public void PropertyGrid_FullRefreshShouldTriggerTypeConverterGetProperties()
4128+
{
4129+
using PropertyGrid propertyGrid = new()
4130+
{
4131+
SelectedObject = new SelectedObject()
4132+
};
4133+
PropertyGridView propertyGridView = propertyGrid.TestAccessor().Dynamic._gridView;
4134+
4135+
MyTypeConverter.GetPropertiesInvokeCount = 0;
4136+
propertyGridView.Refresh(true);
4137+
4138+
int getPropertiesInvokeCount2 = MyTypeConverter.GetPropertiesInvokeCount;
4139+
getPropertiesInvokeCount2.Should().Be(1);
4140+
}
4141+
4142+
#region classes used for PropertyGrid_FullRefreshShouldTriggerTypeConverterGetProperties
4143+
[TypeConverter(typeof(MyTypeConverter))]
4144+
private class SelectedObject
4145+
{
4146+
private string _a;
4147+
private string _b;
4148+
4149+
[RefreshProperties(RefreshProperties.All)]
4150+
public string A
4151+
{
4152+
get { return _a; }
4153+
set { _a = value; }
4154+
}
4155+
4156+
public string B
4157+
{
4158+
get { return _b; }
4159+
set { _b = value; }
4160+
}
4161+
}
4162+
4163+
private class MyTypeConverter : TypeConverter
4164+
{
4165+
public static int GetPropertiesInvokeCount { get; set; }
4166+
public MyTypeConverter()
4167+
: base() { }
4168+
4169+
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
4170+
{
4171+
return true;
4172+
}
4173+
4174+
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
4175+
{
4176+
GetPropertiesInvokeCount++;
4177+
return base.GetProperties(context, value, attributes) ?? TypeDescriptor.GetProperties(value, attributes);
4178+
}
4179+
}
4180+
#endregion
4181+
41254182
private class SubToolStripRenderer : ToolStripRenderer
41264183
{
41274184
}

0 commit comments

Comments
 (0)