diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListBoxDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListBoxDesigner.cs
index 19e7fe9be7a..147bffdd59f 100644
--- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListBoxDesigner.cs
+++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListBoxDesigner.cs
@@ -72,6 +72,12 @@ protected override void PreFilterProperties(IDictionary properties)
properties[nameof(Dock)] = TypeDescriptor.CreateProperty(typeof(ListBoxDesigner), dockProp, []);
}
+ // Wrap Items property to control editor availability based on DataSource
+ if (properties["Items"] is PropertyDescriptor itemsProp && Component is ListBox listBox)
+ {
+ properties["Items"] = new ItemsPropertyDescriptor(itemsProp, listBox);
+ }
+
base.PreFilterProperties(properties);
}
@@ -218,4 +224,47 @@ public override DesignerActionListCollection ActionLists
return _actionLists;
}
}
+
+ ///
+ /// Custom property descriptor that removes the editor when DataSource is set.
+ ///
+ private sealed class ItemsPropertyDescriptor : PropertyDescriptor
+ {
+ private readonly PropertyDescriptor _baseDescriptor;
+ private readonly ListBox _listBox;
+
+ public ItemsPropertyDescriptor(PropertyDescriptor baseDescriptor, ListBox listBox)
+ : base(baseDescriptor)
+ {
+ _baseDescriptor = baseDescriptor;
+ _listBox = listBox;
+ }
+
+ public override Type ComponentType => _baseDescriptor.ComponentType;
+
+ public override bool IsReadOnly => _baseDescriptor.IsReadOnly;
+
+ public override Type PropertyType => _baseDescriptor.PropertyType;
+
+ public override bool CanResetValue(object component) => _baseDescriptor.CanResetValue(component);
+
+ public override object? GetValue(object? component) => _baseDescriptor.GetValue(component);
+
+ public override void ResetValue(object component) => _baseDescriptor.ResetValue(component);
+
+ public override void SetValue(object? component, object? value) => _baseDescriptor.SetValue(component, value);
+
+ public override bool ShouldSerializeValue(object component) => _baseDescriptor.ShouldSerializeValue(component);
+
+ public override object? GetEditor(Type editorBaseType)
+ {
+ // Don't provide an editor if DataSource is set
+ if (_listBox.DataSource is not null)
+ {
+ return null;
+ }
+
+ return _baseDescriptor.GetEditor(editorBaseType);
+ }
+ }
}
diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListControlUnboundActionList.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListControlUnboundActionList.cs
index 187bf8c994e..4cf595c3584 100644
--- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListControlUnboundActionList.cs
+++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ListControlUnboundActionList.cs
@@ -22,13 +22,17 @@ public void InvokeItemsDialog()
public override DesignerActionItemCollection GetSortedActionItems()
{
- DesignerActionItemCollection returnItems =
- [
- new DesignerActionMethodItem(this, "InvokeItemsDialog",
+ DesignerActionItemCollection returnItems = [];
+
+ // Only show "Edit Items..." if DataSource is not set
+ if (Component is ListControl control && control.DataSource is null)
+ {
+ returnItems.Add(new DesignerActionMethodItem(this, "InvokeItemsDialog",
SR.ListControlUnboundActionListEditItemsDisplayName,
SR.ItemsCategoryName,
- SR.ListControlUnboundActionListEditItemsDescription, true),
- ];
+ SR.ListControlUnboundActionListEditItemsDescription, true));
+ }
+
return returnItems;
}
}
diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/ListControlUnboundActionListTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/ListControlUnboundActionListTests.cs
index e9503f46ca8..0b0243ec153 100644
--- a/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/ListControlUnboundActionListTests.cs
+++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Windows/Forms/Design/ListControlUnboundActionListTests.cs
@@ -10,24 +10,28 @@ namespace System.Windows.Forms.Design.Tests;
public sealed class ListControlUnboundActionListTests : IDisposable
{
private readonly ComponentDesigner _designer;
- private readonly Mock _componentMock;
+ private readonly ListBox _listBox;
private readonly ListControlUnboundActionList _actionList;
public ListControlUnboundActionListTests()
{
_designer = new();
- _componentMock = new();
- _designer.Initialize(_componentMock.Object);
+ _listBox = new();
+ _designer.Initialize(_listBox);
_actionList = new(_designer);
}
- public void Dispose() => _designer.Dispose();
+ public void Dispose()
+ {
+ _designer.Dispose();
+ _listBox.Dispose();
+ }
[Fact]
public void Constructor_ShouldInitializeDesigner() => _actionList.Should().NotBeNull();
[Fact]
- public void GetSortedActionItems_ShouldReturnCorrectItems()
+ public void GetSortedActionItems_ShouldReturnCorrectItems_WhenDataSourceIsNull()
{
DesignerActionItemCollection items = _actionList.GetSortedActionItems();
@@ -39,4 +43,15 @@ public void GetSortedActionItems_ShouldReturnCorrectItems()
methodItem.Category.Should().Be(SR.ItemsCategoryName);
methodItem.Description.Should().Be(SR.ListControlUnboundActionListEditItemsDescription);
}
+
+ [Fact]
+ public void GetSortedActionItems_ShouldReturnEmpty_WhenDataSourceIsSet()
+ {
+ _listBox.DataSource = new List { "Item1", "Item2" };
+
+ DesignerActionItemCollection items = _actionList.GetSortedActionItems();
+
+ items.Should().NotBeNull();
+ items.Count.Should().Be(0);
+ }
}