|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections;
using System.Drawing;
using System.Windows.Forms.Layout;
using Moq;
namespace System.Windows.Forms.Tests;
[Collection("Sequential")] // workaround for WebBrowser control corrupting memory when run on multiple UI threads (instantiated via GUID)
public class ControlControlCollectionTests
{
[WinFormsFact]
public void ControlCollection_Ctor_Control()
{
using Control owner = new();
Control.ControlCollection collection = new(owner);
Assert.Empty(collection);
Assert.False(collection.IsReadOnly);
Assert.Same(owner, collection.Owner);
}
[WinFormsFact]
public void ControlCollection_Ctor_NullOwner_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("owner", () => new Control.ControlCollection(null));
}
[WinFormsFact]
public void ControlCollection_Add_ControlNewCollection_Success()
{
using Control owner = new();
using Control control1 = new();
using Control control2 = new();
var collection = new Control.ControlCollection(owner);
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(collection.Cast<Control>().Last(), e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
int layoutCallCount1 = 0;
control1.Layout += (sender, e) => layoutCallCount1++;
int layoutCallCount2 = 0;
control2.Layout += (sender, e) => layoutCallCount2++;
try
{
collection.Add(control1);
Assert.Same(control1, Assert.Single(collection));
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Empty(owner.Controls);
Assert.Equal(0, layoutCallCount1);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
// Add another.
collection.Add(control2);
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Empty(owner.Controls);
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
// Add existing.
Assert.Throws<ArgumentException>(() => collection.Add(control2));
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Empty(owner.Controls);
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
// Add null.
collection.Add(null);
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Add_ControlExistingCollection_Success()
{
using Control owner = new();
using Control control1 = new();
using Control control2 = new();
Control.ControlCollection collection = owner.Controls;
int parentLayoutCallCount = 0;
string affectedProperty = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(collection.Cast<Control>().Last(), e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
int layoutCallCount1 = 0;
control1.Layout += (sender, e) => layoutCallCount1++;
int layoutCallCount2 = 0;
control2.Layout += (sender, e) => layoutCallCount2++;
try
{
affectedProperty = "Parent";
collection.Add(control1);
Assert.Same(control1, Assert.Single(collection));
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(control1, Assert.Single(owner.Controls));
Assert.Equal(0, layoutCallCount1);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
// Add another.
collection.Add(control2);
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Equal(new Control[] { control1, control2 }, owner.Controls.Cast<Control>());
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
// Add existing.
affectedProperty = "ChildIndex";
collection.Add(control1);
Assert.Equal(new Control[] { control2, control1 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Equal(new Control[] { control2, control1 }, owner.Controls.Cast<Control>());
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(3, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
// Add null.
collection.Add(null);
Assert.Equal(new Control[] { control2, control1 }, collection.Cast<Control>());
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Add_ControlHasParent_Success()
{
using Control owner1 = new();
using Control owner2 = new();
using Control control = new();
Control.ControlCollection collection1 = owner1.Controls;
Control.ControlCollection collection2 = owner2.Controls;
int layoutCallCount = 0;
string affectedProperty = "Parent";
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner2, sender);
Assert.Same(collection2.Cast<Control>().Last(), e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
layoutCallCount++;
}
owner2.Layout += parentHandler;
try
{
collection1.Add(control);
collection2.Add(control);
Assert.Same(control, Assert.Single(collection2));
Assert.Empty(collection1);
Assert.Same(owner2, control.Parent);
Assert.Equal(0, control.TabIndex);
Assert.Same(control, Assert.Single(owner2.Controls));
Assert.Equal(1, layoutCallCount);
Assert.False(owner2.IsHandleCreated);
Assert.False(control.IsHandleCreated);
}
finally
{
owner2.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Add_ControlWithCustomLayoutEngine_Success()
{
using Control owner = new();
Control.ControlCollection collection = owner.Controls;
int layoutCallCount = 0;
string affectedProperty = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(collection.Cast<Control>().Last(), e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
layoutCallCount++;
}
owner.Layout += parentHandler;
using CustomLayoutEngineControl control = new();
Mock<LayoutEngine> mockLayoutEngine = new(MockBehavior.Strict);
mockLayoutEngine
.Setup(e => e.InitLayout(control, BoundsSpecified.All))
.Verifiable();
control.SetLayoutEngine(mockLayoutEngine.Object);
try
{
affectedProperty = "Parent";
collection.Add(control);
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(0, control.TabIndex);
Assert.Same(control, Assert.Single(owner.Controls));
Assert.Equal(1, layoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control.IsHandleCreated);
mockLayoutEngine.Verify(e => e.InitLayout(control, BoundsSpecified.All), Times.Once());
// Add existing.
affectedProperty = "ChildIndex";
collection.Add(control);
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(0, control.TabIndex);
Assert.Same(control, Assert.Single(owner.Controls));
Assert.Equal(2, layoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control.IsHandleCreated);
mockLayoutEngine.Verify(e => e.InitLayout(control, BoundsSpecified.All), Times.Once());
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Add_TabIndex_Success()
{
using SubControl owner = new();
Control.ControlCollection collection = owner.Controls;
using SubControl control1 = new()
{
TabIndex = 1
};
int tabIndexChangedCallCount1 = 0;
control1.TabIndexChanged += (sender, e) => tabIndexChangedCallCount1++;
collection.Add(control1);
Assert.Equal(new Control[] { control1 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(1, control1.TabIndex);
Assert.Equal(0, tabIndexChangedCallCount1);
// Add another.
using SubControl control2 = new();
int tabIndexChangedCallCount2 = 0;
control2.TabIndexChanged += (sender, e) => tabIndexChangedCallCount2++;
collection.Add(control2);
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(1, control1.TabIndex);
Assert.Equal(0, tabIndexChangedCallCount1);
Assert.Same(owner, control2.Parent);
Assert.Equal(2, control2.TabIndex);
Assert.Equal(0, tabIndexChangedCallCount2);
// Add another.
control1.TabIndex = 10;
using SubControl control3 = new();
int tabIndexChangedCallCount3 = 0;
control3.TabIndexChanged += (sender, e) => tabIndexChangedCallCount3++;
collection.Add(control3);
Assert.Equal(new Control[] { control1, control2, control3 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(10, control1.TabIndex);
Assert.Equal(1, tabIndexChangedCallCount1);
Assert.Same(owner, control2.Parent);
Assert.Equal(2, control2.TabIndex);
Assert.Equal(0, tabIndexChangedCallCount2);
Assert.Same(owner, control3.Parent);
Assert.Equal(11, control3.TabIndex);
Assert.Equal(0, tabIndexChangedCallCount3);
}
[WinFormsTheory]
[BoolData]
public void ControlCollection_Add_InvokeValueWithoutHandleOwnerWithHandle_CreatedValueIfVisible(bool visible)
{
using Control owner = new();
using Control control = new()
{
Visible = visible
};
Control.ControlCollection collection = owner.Controls;
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
collection.Add(control);
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(visible, control.Visible);
Assert.Equal(visible, control.IsHandleCreated);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
}
[WinFormsTheory]
[BoolData]
public void ControlCollection_Add_InvokeValueWithHandleOwnerWithoutHandle_Success(bool visible)
{
using Control owner = new();
using Control control = new()
{
Visible = visible
};
Control.ControlCollection collection = owner.Controls;
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
control.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
collection.Add(control);
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(visible, control.Visible);
Assert.True(control.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(owner.IsHandleCreated);
}
[WinFormsTheory]
[BoolData]
public void ControlCollection_Add_InvokeValueWithHandleOwnerWithHandleControlNewCollection_Success(bool visible)
{
using Control owner = new();
using Control control = new()
{
Visible = visible
};
var collection = new Control.ControlCollection(owner);
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
control.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
Assert.Throws<ArgumentException>(() => collection.Add(control));
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(visible, control.Visible);
Assert.True(control.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
}
[WinFormsTheory]
[BoolData]
public void ControlCollection_Add_InvokeValueWithHandleOwnerWithHandleControlExistingCollection_Success(bool visible)
{
using Control owner = new();
using Control control = new()
{
Visible = visible
};
Control.ControlCollection collection = owner.Controls;
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
control.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
collection.Add(control);
Assert.Equal(owner.Handle, PInvoke.GetParent(control));
Assert.Same(control, Assert.Single(collection));
Assert.Same(owner, control.Parent);
Assert.Equal(visible, control.Visible);
Assert.True(control.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
}
[WinFormsFact]
public void ControlCollection_Add_InvokeWithHandler_CallsControlAdded()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
Control.ControlCollection collection = owner.Controls;
int parentChangedCallCount = 0;
int callCount = 0;
int parentLayoutCallCount = 0;
child1.ParentChanged += (sender, e) =>
{
Assert.Same(child1, sender);
Assert.Same(EventArgs.Empty, e);
parentChangedCallCount++;
};
child2.ParentChanged += (sender, e) =>
{
Assert.Same(child2, sender);
Assert.Same(EventArgs.Empty, e);
parentChangedCallCount++;
};
object affectedControl = null;
string affectedProperty = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(affectedControl, e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
void handler(object sender, ControlEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.Control);
Assert.Equal(parentChangedCallCount - 1, callCount);
Assert.Equal(parentLayoutCallCount - 1, callCount);
callCount++;
}
try
{
// Call with handler.
owner.ControlAdded += handler;
affectedControl = child1;
affectedProperty = "Parent";
collection.Add(child1);
Assert.Same(owner, child1.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(1, callCount);
// Call again.
affectedProperty = "ChildIndex";
collection.Add(child1);
Assert.Same(owner, child1.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.Equal(1, callCount);
// Remove handler.
owner.ControlAdded -= handler;
affectedControl = child2;
affectedProperty = "Parent";
collection.Add(child2);
Assert.Same(owner, child2.Parent);
Assert.Equal(2, parentChangedCallCount);
Assert.Equal(3, parentLayoutCallCount);
Assert.Equal(1, callCount);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Add_InvokeWithNonOverriddenProperties_DoesNotCallPropertyHandlers()
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) => parentChangedCallCount++;
control.EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
control.FontChanged += (sender, e) => fontChangedCallCount++;
control.ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
control.BackColorChanged += (sender, e) => backColorChangedCallCount++;
control.RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Add(control);
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Null(control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
[WinFormsFact]
public void ControlCollection_Add_InvokeWithNonOverriddenPropertiesWithHandle_DoesNotCallPropertyHandlers()
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner);
Assert.NotEqual(IntPtr.Zero, control.Handle);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) => parentChangedCallCount++;
control.EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
control.FontChanged += (sender, e) => fontChangedCallCount++;
control.ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
control.BackColorChanged += (sender, e) => backColorChangedCallCount++;
control.RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Add(control);
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Null(control.BindingContext);
Assert.Equal(1, bindingContextChangedCallCount);
}
public static IEnumerable<object[]> Add_OverriddenProperties_TestData()
{
BindingContext parentContext = [];
BindingContext childContext = [];
yield return new object[] { parentContext, childContext, childContext };
yield return new object[] { parentContext, null, parentContext };
yield return new object[] { null, childContext, childContext };
yield return new object[] { null, null, null };
}
[WinFormsTheory]
[MemberData(nameof(Add_OverriddenProperties_TestData))]
public void ControlCollection_Add_InvokeWithOverriddenProperties_CallsPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext)
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner);
owner.Enabled = false;
Assert.True(control.Enabled);
owner.Visible = false;
Assert.True(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Equal(Control.DefaultFont, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Control.DefaultBackColor, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.No, control.RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(bindingContext, control.BindingContext);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
Assert.Equal(enabledChangedCallCount, parentChangedCallCount);
Assert.Equal(visibleChangedCallCount, parentChangedCallCount);
Assert.Equal(fontChangedCallCount, parentChangedCallCount);
Assert.Equal(foreColorChangedCallCount, parentChangedCallCount);
Assert.Equal(backColorChangedCallCount, parentChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, parentChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, parentChangedCallCount);
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
control.EnabledChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, enabledChangedCallCount);
Assert.Equal(visibleChangedCallCount, enabledChangedCallCount);
Assert.Equal(fontChangedCallCount, enabledChangedCallCount);
Assert.Equal(foreColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(backColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, enabledChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, enabledChangedCallCount);
enabledChangedCallCount++;
};
control.VisibleChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(fontChangedCallCount, visibleChangedCallCount);
Assert.Equal(foreColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(backColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, visibleChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, visibleChangedCallCount);
visibleChangedCallCount++;
};
control.FontChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(foreColorChangedCallCount, fontChangedCallCount);
Assert.Equal(backColorChangedCallCount, fontChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, fontChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, fontChangedCallCount);
fontChangedCallCount++;
};
control.ForeColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(backColorChangedCallCount, foreColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, foreColorChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, foreColorChangedCallCount);
foreColorChangedCallCount++;
};
control.BackColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, backColorChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, backColorChangedCallCount);
backColorChangedCallCount++;
};
control.RightToLeftChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(backColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, rightToLeftChangedCallCount);
rightToLeftChangedCallCount++;
};
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
try
{
collection.Add(control);
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.False(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.False(control.Visible);
Assert.Equal(1, visibleChangedCallCount);
Assert.Same(font, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Color.Red, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Color.Blue, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.Yes, control.RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
public static IEnumerable<object[]> Add_OverriddenPropertiesWithHandle_TestData()
{
BindingContext parentContext = [];
BindingContext childContext = [];
yield return new object[] { parentContext, childContext, childContext, 0 };
yield return new object[] { parentContext, null, parentContext, 1 };
yield return new object[] { null, childContext, childContext, 0 };
yield return new object[] { null, null, null, 1 };
}
[WinFormsTheory]
[MemberData(nameof(Add_OverriddenPropertiesWithHandle_TestData))]
public void ControlCollection_Add_InvokeWithOverriddenPropertiesWithHandle_CallsPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext, int expectedBindingContextChangedCallCount)
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner);
owner.Enabled = false;
Assert.True(control.Enabled);
owner.Visible = false;
Assert.True(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Equal(Control.DefaultFont, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Control.DefaultBackColor, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.No, control.RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(bindingContext, control.BindingContext);
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
control.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
Assert.Equal(enabledChangedCallCount, parentChangedCallCount);
Assert.Equal(visibleChangedCallCount, parentChangedCallCount);
Assert.Equal(fontChangedCallCount, parentChangedCallCount);
Assert.Equal(foreColorChangedCallCount, parentChangedCallCount);
Assert.Equal(backColorChangedCallCount, parentChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, parentChangedCallCount);
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
control.EnabledChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, enabledChangedCallCount);
Assert.Equal(visibleChangedCallCount, enabledChangedCallCount);
Assert.Equal(fontChangedCallCount, enabledChangedCallCount);
Assert.Equal(foreColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(backColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, enabledChangedCallCount);
enabledChangedCallCount++;
};
control.VisibleChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(fontChangedCallCount, visibleChangedCallCount);
Assert.Equal(foreColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(backColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, visibleChangedCallCount);
visibleChangedCallCount++;
};
control.FontChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(foreColorChangedCallCount, fontChangedCallCount);
Assert.Equal(backColorChangedCallCount, fontChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, fontChangedCallCount);
fontChangedCallCount++;
};
control.ForeColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(backColorChangedCallCount, foreColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, foreColorChangedCallCount);
foreColorChangedCallCount++;
};
control.BackColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, backColorChangedCallCount);
backColorChangedCallCount++;
};
control.RightToLeftChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(backColorChangedCallCount - 1, rightToLeftChangedCallCount);
rightToLeftChangedCallCount++;
};
control.BindingContextChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, bindingContextChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, bindingContextChangedCallCount);
Assert.Equal(visibleChangedCallCount - 1, bindingContextChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, bindingContextChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, bindingContextChangedCallCount);
Assert.Equal(backColorChangedCallCount - 1, bindingContextChangedCallCount);
bindingContextChangedCallCount++;
};
try
{
collection.Add(control);
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.False(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.False(control.Visible);
Assert.Equal(1, visibleChangedCallCount);
Assert.Same(font, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Color.Red, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Color.Blue, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.Yes, control.RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.Equal(expectedBindingContextChangedCallCount, bindingContextChangedCallCount);
Assert.True(control.IsHandleCreated);
Assert.Equal(4, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(1, createdCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
[WinFormsTheory]
[MemberData(nameof(Add_OverriddenProperties_TestData))]
public void ControlCollection_Add_InvokeWithOverriddenPropertiesAxHost_DoesNotCallPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext)
{
using Control owner = new();
using SubAxHost control = new("8856f961-340a-11d0-a96b-00c04fd705a2");
var collection = new Control.ControlCollection(owner);
owner.Enabled = false;
Assert.True(control.Enabled);
owner.Visible = false;
Assert.True(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Equal(Control.DefaultFont, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Control.DefaultBackColor, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.No, ((Control)control).RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(bindingContext, control.BindingContext);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
((Control)control).EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
((Control)control).FontChanged += (sender, e) => fontChangedCallCount++;
((Control)control).ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
((Control)control).BackColorChanged += (sender, e) => backColorChangedCallCount++;
((Control)control).RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
((Control)control).BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Add(control);
try
{
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.False(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.False(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Same(font, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Color.Red, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Color.Blue, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.Yes, ((Control)control).RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
[WinFormsTheory]
[MemberData(nameof(Add_OverriddenPropertiesWithHandle_TestData))]
public void ControlCollection_Add_InvokeWithOverriddenPropertiesAxHostWithHandle_CallSPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext, int expectedBindingContextChangedCallCount)
{
using Control owner = new();
using SubAxHost control = new("8856f961-340a-11d0-a96b-00c04fd705a2");
var collection = new Control.ControlCollection(owner);
owner.Enabled = false;
Assert.True(control.Enabled);
owner.Visible = false;
Assert.True(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Equal(Control.DefaultFont, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Control.DefaultBackColor, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.No, ((Control)control).RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(bindingContext, control.BindingContext);
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
((Control)control).StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
((Control)control).EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
((Control)control).FontChanged += (sender, e) => fontChangedCallCount++;
((Control)control).ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
((Control)control).BackColorChanged += (sender, e) => backColorChangedCallCount++;
((Control)control).RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
((Control)control).BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
try
{
collection.Add(control);
Assert.Same(owner, control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.False(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.False(control.Visible);
Assert.Equal(1, visibleChangedCallCount);
Assert.Same(font, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Color.Red, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Color.Blue, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.Yes, ((Control)control).RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.Equal(expectedBindingContextChangedCallCount, bindingContextChangedCallCount);
Assert.True(control.IsHandleCreated);
Assert.Equal(6, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
private class SubAxHost : AxHost
{
public SubAxHost(string clsid) : base(clsid)
{
}
public SubAxHost(string clsid, int flags) : base(clsid, flags)
{
}
}
[WinFormsFact]
public void ControlCollection_Add_TopLevelValue_ThrowsArgumentException()
{
using Control owner = new();
using SubControl control = new();
control.SetTopLevel(true);
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(control));
}
[Fact] // cross-thread access
public void ControlCollection_Add_DifferentThreadValueOwner_ThrowsArgumentException()
{
Control owner = null;
try
{
Thread thread = new(() =>
{
owner = new Control();
Assert.NotEqual(IntPtr.Zero, owner.Handle);
});
thread.Start();
thread.Join();
using Control control = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(control));
}
finally
{
owner?.Dispose();
}
}
[Fact] // cross-thread access
public void ControlCollection_Add_DifferentThreadValueControl_ThrowsArgumentException()
{
Control control = null;
try
{
Thread thread = new(() =>
{
control = new Control();
Assert.NotEqual(IntPtr.Zero, control.Handle);
});
thread.Start();
thread.Join();
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(control));
}
finally
{
control?.Dispose();
}
}
[WinFormsFact]
public void ControlCollection_Add_SameAsOwner_ThrowsArgumentException()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(owner));
}
[WinFormsFact]
public void ControlCollection_Add_OwnerParent_ThrowsArgumentException()
{
using Control parent = new();
using Control owner = new()
{
Parent = parent
};
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(parent));
}
[WinFormsFact]
public void ControlCollection_Add_OwnerGrandParent_ThrowsArgumentException()
{
using Control grandparent = new();
using Control parent = new()
{
Parent = grandparent
};
using Control owner = new()
{
Parent = parent
};
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>(() => collection.Add(grandparent));
}
[WinFormsFact]
public void ControlCollection_AddRange_Invoke_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
Control.ControlCollection collection = owner.Controls;
int parentLayoutCallCount = 0;
object affectedControl = null;
string affectedProperty = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(affectedControl, e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
int controlAddedCallCount = 0;
owner.ControlAdded += (sender, e) => controlAddedCallCount++;
try
{
affectedControl = child3;
affectedProperty = "Parent";
collection.AddRange([child1, child2, null, child3]);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Same(owner, child3.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(3, controlAddedCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
affectedControl = child1;
affectedProperty = "ChildIndex";
collection.AddRange([child1, child2, null, child3]);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Same(owner, child3.Parent);
Assert.Equal(2, parentLayoutCallCount);
Assert.Equal(3, controlAddedCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Add empty.
collection.AddRange(Array.Empty<Control>());
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Same(owner, child3.Parent);
Assert.Equal(2, parentLayoutCallCount);
Assert.Equal(3, controlAddedCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_AddRange_NullControls_ThrowsArgumentNullException()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentNullException>("controls", () => collection.AddRange(null));
}
[WinFormsFact]
public void ControlCollection_Clear_Invoke_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
int parentLayoutCallCount = 0;
owner.Layout += (sender, e) =>
{
Assert.Same(owner, sender);
Assert.Same(child3, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
};
int controlRemovedCallCount = 0;
owner.ControlRemoved += (sender, e) => controlRemovedCallCount++;
collection.Clear();
Assert.Empty(collection);
Assert.Null(child1.Parent);
Assert.Null(child2.Parent);
Assert.Null(child3.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(3, controlRemovedCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Clear again.
collection.Clear();
Assert.Empty(collection);
Assert.Null(child1.Parent);
Assert.Null(child2.Parent);
Assert.Null(child3.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(3, controlRemovedCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
[WinFormsFact]
public void ControlCollection_Clone_Invoke_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var sourceCollection = new Control.ControlCollection(owner);
ICloneable iCloneable = sourceCollection;
sourceCollection.Add(child1);
sourceCollection.Add(child2);
sourceCollection.Add(child3);
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
var collection = Assert.IsType<Control.ControlCollection>(iCloneable.Clone());
Assert.NotSame(sourceCollection, collection);
Assert.Equal(new Control[] { child1, child2, child3 }, sourceCollection.Cast<Control>());
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.False(collection.IsReadOnly);
Assert.Same(owner, collection.Owner);
Assert.Same(owner, child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(0, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Contains_Invoke_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.True(collection.Contains(child1));
Assert.True(collection.Contains(child2));
Assert.False(collection.Contains(new Control()));
Assert.False(collection.Contains(null));
}
[WinFormsTheory]
[InlineData(null, false)]
[InlineData("", false)]
[InlineData("name1", true)]
[InlineData("NAME1", true)]
[InlineData("name2", true)]
[InlineData("NoSuchName", false)]
[InlineData("abcd", false)]
[InlineData("abcde", false)]
[InlineData("abcdef", false)]
public void ControlCollection_ContainsKey_Invoke_ReturnsExpected(string key, bool expected)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
Assert.Equal(expected, collection.ContainsKey(key));
// Call again.
Assert.Equal(expected, collection.ContainsKey(key));
Assert.Equal(-1, collection.IndexOfKey("NoSuchKey"));
}
[WinFormsTheory]
[InlineData("name2")]
[InlineData("NAME2")]
public void ControlCollection_Find_InvokeKeyExists_ReturnsExpected(string key)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
using Control grandchild1 = new()
{
Name = "name1"
};
using Control grandchild2 = new()
{
Name = "name2"
};
using Control grandchild3 = new()
{
Name = "name2"
};
child3.Controls.Add(grandchild1);
child3.Controls.Add(grandchild2);
child3.Controls.Add(grandchild3);
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
collection.Add(child3);
// Search all children.
Assert.Equal([child2, child3, grandchild2, grandchild3], collection.Find(key, searchAllChildren: true));
// Call again.
Assert.Equal([child2, child3, grandchild2, grandchild3], collection.Find(key, searchAllChildren: true));
// Don't search all children.
Assert.Equal([child2, child3], collection.Find(key, searchAllChildren: false));
// Call again.
Assert.Equal([child2, child3], collection.Find(key, searchAllChildren: false));
}
[WinFormsTheory]
[InlineData("NoSuchName")]
[InlineData("abcd")]
[InlineData("abcde")]
[InlineData("abcdef")]
public void ControlCollection_Find_InvokeNoSuchKey_ReturnsEmpty(string key)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
collection.Add(child3);
Assert.Empty(collection.Find(key, searchAllChildren: true));
Assert.Empty(collection.Find(key, searchAllChildren: false));
}
[WinFormsTheory]
[NullAndEmptyStringData]
public void ControlCollection_Find_NullOrEmptyKey_ThrowsArgumentNullException(string key)
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentNullException>("key", () => collection.Find(key, searchAllChildren: true));
Assert.Throws<ArgumentNullException>("key", () => collection.Find(key, searchAllChildren: false));
}
[WinFormsFact]
public void ControlCollection_GetChildIndex_InvokeControl_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.Equal(0, collection.GetChildIndex(child1));
Assert.Equal(1, collection.GetChildIndex(child2));
}
[WinFormsFact]
public void ControlCollection_GetChildIndex_InvokeControlBoolThrowException_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.Equal(0, collection.GetChildIndex(child1, throwException: true));
Assert.Equal(1, collection.GetChildIndex(child2, throwException: true));
}
[WinFormsFact]
public void ControlCollection_GetChildIndex_InvokeControlBoolNoSuchControl_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.Equal(0, collection.GetChildIndex(child1, throwException: false));
Assert.Equal(1, collection.GetChildIndex(child2, throwException: false));
Assert.Equal(-1, collection.GetChildIndex(new Control(), throwException: false));
Assert.Equal(-1, collection.GetChildIndex(null, throwException: false));
}
public static IEnumerable<object[]> GetChildIndex_NoSuchControl_TestData()
{
yield return new object[] { new Control() };
yield return new object[] { null };
}
[WinFormsTheory]
[MemberData(nameof(GetChildIndex_NoSuchControl_TestData))]
public void ControlCollection_GetChildIndex_NoSuchControl_ThrowsArgumentException(Control child)
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.Throws<ArgumentException>(() => collection.GetChildIndex(child));
Assert.Throws<ArgumentException>(() => collection.GetChildIndex(child));
}
[WinFormsFact]
public void ControlCollection_GetEnumerator_InvokeEmpty_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
IEnumerator enumerator = collection.GetEnumerator();
for (int i = 0; i < 2; i++)
{
Assert.Null(enumerator.Current);
Assert.False(enumerator.MoveNext());
Assert.Null(enumerator.Current);
// Call again.
Assert.False(enumerator.MoveNext());
Assert.Null(enumerator.Current);
enumerator.Reset();
}
}
[WinFormsFact]
public void ControlCollection_GetEnumerator_InvokeNotEmpty_ReturnsExpected()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
IEnumerator enumerator = collection.GetEnumerator();
for (int i = 0; i < 2; i++)
{
Assert.Null(enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child1, enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child2, enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
Assert.False(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
// Call again.
Assert.False(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
enumerator.Reset();
}
}
[WinFormsFact]
public void ControlCollection_GetEnumerator_AddDuringEnumeration_ReturnsExpected()
{
using Control owner = new();
using Control child = new();
var collection = new Control.ControlCollection(owner);
IEnumerator enumerator = collection.GetEnumerator();
collection.Add(child);
for (int i = 0; i < 2; i++)
{
Assert.Null(enumerator.Current);
Assert.False(enumerator.MoveNext());
Assert.Null(enumerator.Current);
// Call again.
Assert.False(enumerator.MoveNext());
Assert.Null(enumerator.Current);
enumerator.Reset();
}
}
[WinFormsFact]
public void ControlCollection_GetEnumerator_InvokeRemoveBeforeEnumeration_ReturnsExpected()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
IEnumerator enumerator = collection.GetEnumerator();
collection.Remove(child1);
Assert.Null(enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child2, enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
Assert.False(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
// Call again.
Assert.False(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
}
[WinFormsFact]
public void ControlCollection_GetEnumerator_InvokeRemoveAtEndOfEnumeration_ReturnsExpected()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
IEnumerator enumerator = collection.GetEnumerator();
Assert.Null(enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child1, enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child2, enumerator.Current);
Assert.True(enumerator.MoveNext());
Assert.Same(child3, enumerator.Current);
collection.Remove(child1);
Assert.Throws<ArgumentOutOfRangeException>("index", () => enumerator.Current);
Assert.False(enumerator.MoveNext());
Assert.Throws<ArgumentOutOfRangeException>("index", () => enumerator.Current);
// Call again.
Assert.False(enumerator.MoveNext());
Assert.Throws<ArgumentOutOfRangeException>("index", () => enumerator.Current);
collection.Add(child1);
Assert.Same(child1, enumerator.Current);
}
[WinFormsFact]
public void ControlCollection_IndexOf_Invoke_ReturnsExpected()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
using Control child1 = new();
using Control child2 = new();
collection.Add(child1);
collection.Add(child2);
Assert.Equal(0, collection.IndexOf(child1));
Assert.Equal(1, collection.IndexOf(child2));
Assert.Equal(-1, collection.IndexOf(new Control()));
Assert.Equal(-1, collection.IndexOf(null));
}
[WinFormsTheory]
[InlineData(null, -1)]
[InlineData("", -1)]
[InlineData("name1", 0)]
[InlineData("NAME1", 0)]
[InlineData("name2", 1)]
[InlineData("NoSuchName", -1)]
[InlineData("abcd", -1)]
[InlineData("abcde", -1)]
[InlineData("abcdef", -1)]
public void ControlCollection_IndexOfKey_Invoke_ReturnsExpected(string key, int expected)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
Assert.Equal(expected, collection.IndexOfKey(key));
// Call again.
Assert.Equal(expected, collection.IndexOfKey(key));
Assert.Equal(-1, collection.IndexOfKey("NoSuchKey"));
}
[WinFormsTheory]
[InlineData("name1", 0)]
[InlineData("NAME1", 0)]
[InlineData("name2", 1)]
public void ControlCollection_Item_GetStringValidKey_ReturnsExpected(string key, int expectedIndex)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
Assert.Equal(collection[expectedIndex], collection[key]);
// Call again.
Assert.Equal(collection[expectedIndex], collection[key]);
Assert.Null(collection["NoSuchKey"]);
}
[WinFormsTheory]
[InlineData(null)]
[InlineData("")]
[InlineData("NoSuchName")]
[InlineData("abcd")]
[InlineData("abcde")]
[InlineData("abcdef")]
public void ControlCollection_Item_GetStringNoSuchKey_ReturnsNull(string key)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
Assert.Null(collection[key]);
// Call again.
Assert.Null(collection[key]);
Assert.Null(collection["NoSuchKey"]);
}
[WinFormsFact]
public void ControlCollection_Item_GetInt_ReturnsExpected()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
Assert.Same(child1, collection[0]);
Assert.Same(child2, collection[1]);
Assert.Same(child3, collection[2]);
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void ControlCollection_Item_GetInvalidIndexEmpty_ThrowsArgumentOutOfRangeException(int index)
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection[index]);
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(1)]
[InlineData(2)]
public void ControlCollection_Item_GetInvalidIndexNotEmpty_ThrowsArgumentOutOfRangeException(int index)
{
using Control owner = new();
using Control child = new();
var collection = new Control.ControlCollection(owner)
{
child
};
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection[index]);
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeChildWithoutHandleOwnerWithoutHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2
};
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove again.
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove null.
collection.Remove(null);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeContainerControlParent_Success()
{
using ContainerControl owner = new();
using Control child1 = new();
using Control child2 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2
};
owner.ActiveControl = child1;
Assert.Same(child1, owner.ActiveControl);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Null(owner.ActiveControl);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove again.
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Null(owner.ActiveControl);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove null.
collection.Remove(null);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Null(owner.ActiveControl);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeChildWithHandleOwnerWithoutHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
Assert.NotEqual(IntPtr.Zero, child1.Handle);
int invalidatedCallCount = 0;
child1.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
child1.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
child1.HandleCreated += (sender, e) => createdCallCount++;
try
{
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
// Remove again.
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
// Remove null.
collection.Remove(null);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeChildWithHandleOwnerWithHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int invalidatedCallCount = 0;
child1.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
child1.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
child1.HandleCreated += (sender, e) => createdCallCount++;
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
try
{
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
// Remove again.
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
// Remove null.
collection.Remove(null);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeChildFromAnotherParent_Nop()
{
using Control owner1 = new();
using Control owner2 = new();
using Control control1 = new();
using Control control2 = new();
using Control control3 = new();
var collection1 = new Control.ControlCollection(owner1);
var collection2 = new Control.ControlCollection(owner2);
collection1.Add(control1);
collection2.Add(control2);
// Remove with parent.
collection1.Remove(control2);
Assert.Equal(new Control[] { control1 }, collection1.Cast<Control>());
Assert.Equal(new Control[] { control2 }, collection2.Cast<Control>());
Assert.Same(owner1, control1.Parent);
Assert.Same(owner2, control2.Parent);
// Remove without parent.
collection1.Remove(control3);
Assert.Equal(new Control[] { control1 }, collection1.Cast<Control>());
Assert.Equal(new Control[] { control2 }, collection2.Cast<Control>());
Assert.Same(owner1, control1.Parent);
Assert.Same(owner2, control2.Parent);
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeWithNonOverriddenProperties_DoesNotCallPropertyHandlers()
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner)
{
control
};
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) => parentChangedCallCount++;
control.EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
control.FontChanged += (sender, e) => fontChangedCallCount++;
control.ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
control.BackColorChanged += (sender, e) => backColorChangedCallCount++;
control.RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Null(control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeWithNonOverriddenPropertiesWithHandle_DoesNotCallPropertyHandlers()
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner)
{
control
};
Assert.NotEqual(IntPtr.Zero, control.Handle);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) => parentChangedCallCount++;
control.EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
control.FontChanged += (sender, e) => fontChangedCallCount++;
control.ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
control.BackColorChanged += (sender, e) => backColorChangedCallCount++;
control.RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(2, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Null(control.BindingContext);
Assert.Equal(1, bindingContextChangedCallCount);
}
public static IEnumerable<object[]> Remove_OverriddenProperties_TestData()
{
BindingContext parentContext = [];
BindingContext childContext = [];
yield return new object[] { parentContext, childContext, childContext };
yield return new object[] { parentContext, null, parentContext };
yield return new object[] { null, childContext, childContext };
yield return new object[] { null, null, null };
}
[WinFormsTheory]
[MemberData(nameof(Remove_OverriddenProperties_TestData))]
public void ControlCollection_Remove_InvokeWithOverriddenProperties_CallsPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext)
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner)
{
control
};
owner.Enabled = false;
Assert.False(control.Enabled);
owner.Visible = false;
Assert.False(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Same(font, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Color.Red, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Color.Blue, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.Yes, control.RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(expectedBindingContext, control.BindingContext);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) =>
{
Assert.Equal(enabledChangedCallCount, parentChangedCallCount);
Assert.Equal(visibleChangedCallCount, parentChangedCallCount);
Assert.Equal(fontChangedCallCount, parentChangedCallCount);
Assert.Equal(foreColorChangedCallCount, parentChangedCallCount);
Assert.Equal(backColorChangedCallCount, parentChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, parentChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, parentChangedCallCount);
parentChangedCallCount++;
};
control.EnabledChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, enabledChangedCallCount);
Assert.Equal(visibleChangedCallCount, enabledChangedCallCount);
Assert.Equal(fontChangedCallCount, enabledChangedCallCount);
Assert.Equal(foreColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(backColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, enabledChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, enabledChangedCallCount);
enabledChangedCallCount++;
};
control.VisibleChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, visibleChangedCallCount);
Assert.Equal(fontChangedCallCount, visibleChangedCallCount);
Assert.Equal(foreColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(backColorChangedCallCount, visibleChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, visibleChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, visibleChangedCallCount);
visibleChangedCallCount++;
};
control.FontChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(visibleChangedCallCount, fontChangedCallCount);
Assert.Equal(foreColorChangedCallCount, fontChangedCallCount);
Assert.Equal(backColorChangedCallCount, fontChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, fontChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, fontChangedCallCount);
fontChangedCallCount++;
};
control.ForeColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(visibleChangedCallCount, foreColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(backColorChangedCallCount, foreColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, foreColorChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, foreColorChangedCallCount);
foreColorChangedCallCount++;
};
control.BackColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(visibleChangedCallCount, backColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, backColorChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, backColorChangedCallCount);
backColorChangedCallCount++;
};
control.RightToLeftChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(visibleChangedCallCount, rightToLeftChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(backColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(bindingContextChangedCallCount, rightToLeftChangedCallCount);
rightToLeftChangedCallCount++;
};
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(bindingContext, control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
public static IEnumerable<object[]> Remove_OverriddenPropertiesWithHandle_TestData()
{
BindingContext parentContext = [];
BindingContext childContext = [];
yield return new object[] { parentContext, childContext, childContext, 0 };
yield return new object[] { parentContext, null, parentContext, 1 };
yield return new object[] { null, childContext, childContext, 0 };
yield return new object[] { null, null, null, 1 };
}
[WinFormsTheory]
[MemberData(nameof(Remove_OverriddenPropertiesWithHandle_TestData))]
public void ControlCollection_Remove_InvokeWithOverriddenPropertiesWithHandle_CallsPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext, int expectedBindingContextChangedCallCount)
{
using Control owner = new();
using Control control = new();
var collection = new Control.ControlCollection(owner)
{
control
};
owner.Enabled = false;
Assert.False(control.Enabled);
owner.Visible = false;
Assert.False(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Same(font, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Color.Red, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Color.Blue, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.Yes, control.RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
control.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
Assert.Equal(enabledChangedCallCount, parentChangedCallCount);
Assert.Equal(fontChangedCallCount, parentChangedCallCount);
Assert.Equal(foreColorChangedCallCount, parentChangedCallCount);
Assert.Equal(backColorChangedCallCount, parentChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, parentChangedCallCount);
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
control.EnabledChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, enabledChangedCallCount);
Assert.Equal(fontChangedCallCount, enabledChangedCallCount);
Assert.Equal(foreColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(backColorChangedCallCount, enabledChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, enabledChangedCallCount);
enabledChangedCallCount++;
};
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
control.FontChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, fontChangedCallCount);
Assert.Equal(foreColorChangedCallCount, fontChangedCallCount);
Assert.Equal(backColorChangedCallCount, fontChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, fontChangedCallCount);
fontChangedCallCount++;
};
control.ForeColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, foreColorChangedCallCount);
Assert.Equal(backColorChangedCallCount, foreColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, foreColorChangedCallCount);
foreColorChangedCallCount++;
};
control.BackColorChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, backColorChangedCallCount);
Assert.Equal(rightToLeftChangedCallCount, backColorChangedCallCount);
backColorChangedCallCount++;
};
control.RightToLeftChanged += (sender, e) =>
{
Assert.Equal(parentChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(enabledChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(fontChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(foreColorChangedCallCount - 1, rightToLeftChangedCallCount);
Assert.Equal(backColorChangedCallCount - 1, rightToLeftChangedCallCount);
rightToLeftChangedCallCount++;
};
control.BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
try
{
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(2, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, control.RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(bindingContext, control.BindingContext);
Assert.Equal(expectedBindingContextChangedCallCount * 2, bindingContextChangedCallCount);
Assert.True(control.IsHandleCreated);
Assert.Equal(4, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(1, createdCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
[WinFormsTheory]
[MemberData(nameof(Remove_OverriddenProperties_TestData))]
public void ControlCollection_Remove_InvokeWithOverriddenPropertiesAxHost_DoesNotCallPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext)
{
using Control owner = new();
using SubAxHost control = new("8856f961-340a-11d0-a96b-00c04fd705a2");
var collection = new Control.ControlCollection(owner)
{
control
};
owner.Enabled = false;
Assert.False(control.Enabled);
owner.Visible = false;
Assert.False(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Same(font, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Color.Red, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Color.Blue, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.Yes, ((Control)control).RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(expectedBindingContext, control.BindingContext);
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
control.ParentChanged += (sender, e) => parentChangedCallCount++;
((Control)control).EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
((Control)control).FontChanged += (sender, e) => fontChangedCallCount++;
((Control)control).ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
((Control)control).BackColorChanged += (sender, e) => backColorChangedCallCount++;
((Control)control).RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
((Control)control).BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(0, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(0, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(0, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(0, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(0, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, ((Control)control).RightToLeft);
Assert.Equal(0, rightToLeftChangedCallCount);
Assert.Same(bindingContext, control.BindingContext);
Assert.Equal(0, bindingContextChangedCallCount);
}
[WinFormsTheory]
[MemberData(nameof(Remove_OverriddenPropertiesWithHandle_TestData))]
public void ControlCollection_Remove_InvokeWithOverriddenPropertiesAxHostWithHandle_CallSPropertyHandlers(BindingContext parentBindingContext, BindingContext bindingContext, BindingContext expectedBindingContext, int expectedBindingContextChangedCallCount)
{
using Control owner = new();
using SubAxHost control = new("8856f961-340a-11d0-a96b-00c04fd705a2");
var collection = new Control.ControlCollection(owner)
{
control
};
owner.Enabled = false;
Assert.False(control.Enabled);
owner.Visible = false;
Assert.False(control.Visible);
Font font = new("Arial", 8.25f);
owner.Font = font;
Assert.Same(font, control.Font);
owner.ForeColor = Color.Red;
Assert.Equal(Color.Red, control.ForeColor);
owner.BackColor = Color.Blue;
Assert.Equal(Color.Blue, control.BackColor);
owner.RightToLeft = RightToLeft.Yes;
Assert.Equal(RightToLeft.Yes, ((Control)control).RightToLeft);
owner.BindingContext = parentBindingContext;
control.BindingContext = bindingContext;
Assert.Same(expectedBindingContext, control.BindingContext);
Assert.NotEqual(IntPtr.Zero, control.Handle);
int invalidatedCallCount = 0;
control.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
((Control)control).StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
control.HandleCreated += (sender, e) => createdCallCount++;
int parentChangedCallCount = 0;
int enabledChangedCallCount = 0;
int visibleChangedCallCount = 0;
int fontChangedCallCount = 0;
int foreColorChangedCallCount = 0;
int backColorChangedCallCount = 0;
int rightToLeftChangedCallCount = 0;
int bindingContextChangedCallCount = 0;
void parentChangedHandler(object sender, EventArgs e)
{
parentChangedCallCount++;
}
control.ParentChanged += parentChangedHandler;
((Control)control).EnabledChanged += (sender, e) => enabledChangedCallCount++;
control.VisibleChanged += (sender, e) => visibleChangedCallCount++;
((Control)control).FontChanged += (sender, e) => fontChangedCallCount++;
((Control)control).ForeColorChanged += (sender, e) => foreColorChangedCallCount++;
((Control)control).BackColorChanged += (sender, e) => backColorChangedCallCount++;
((Control)control).RightToLeftChanged += (sender, e) => rightToLeftChangedCallCount++;
((Control)control).BindingContextChanged += (sender, e) => bindingContextChangedCallCount++;
try
{
collection.Remove(control);
Assert.Null(control.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.True(control.Enabled);
Assert.Equal(1, enabledChangedCallCount);
Assert.True(control.Visible);
Assert.Equal(2, visibleChangedCallCount);
Assert.Equal(Control.DefaultFont, control.Font);
Assert.Equal(1, fontChangedCallCount);
Assert.Equal(Control.DefaultForeColor, control.ForeColor);
Assert.Equal(1, foreColorChangedCallCount);
Assert.Equal(Control.DefaultBackColor, control.BackColor);
Assert.Equal(1, backColorChangedCallCount);
Assert.Equal(RightToLeft.No, ((Control)control).RightToLeft);
Assert.Equal(1, rightToLeftChangedCallCount);
Assert.Same(bindingContext, control.BindingContext);
Assert.Equal(expectedBindingContextChangedCallCount, bindingContextChangedCallCount);
Assert.True(control.IsHandleCreated);
Assert.Equal(7, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(1, createdCallCount);
}
finally
{
control.ParentChanged -= parentChangedHandler;
}
}
[WinFormsFact]
public void ControlCollection_Remove_InvokeWithHandler_CallsControlRemoved()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2
};
int parentChangedCallCount = 0;
int callCount = 0;
int parentLayoutCallCount = 0;
child1.ParentChanged += (sender, e) =>
{
Assert.Same(child1, sender);
Assert.Same(EventArgs.Empty, e);
Assert.Equal(callCount, parentChangedCallCount);
Assert.Equal(parentLayoutCallCount, parentChangedCallCount);
parentChangedCallCount++;
};
child2.ParentChanged += (sender, e) =>
{
Assert.Same(child2, sender);
Assert.Same(EventArgs.Empty, e);
Assert.Equal(callCount, parentChangedCallCount);
Assert.Equal(parentLayoutCallCount, parentChangedCallCount);
parentChangedCallCount++;
};
object affectedControl = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(affectedControl, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
Assert.Equal(parentChangedCallCount - 1, parentLayoutCallCount);
Assert.Equal(callCount, parentLayoutCallCount);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
void handler(object sender, ControlEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.Control);
Assert.Equal(parentChangedCallCount - 1, callCount);
Assert.Equal(parentLayoutCallCount - 1, callCount);
callCount++;
}
// Call with handler.
owner.ControlRemoved += handler;
affectedControl = child1;
collection.Remove(child1);
Assert.Null(child1.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(1, callCount);
// Call again.
collection.Remove(child1);
Assert.Null(child1.Parent);
Assert.Equal(1, parentChangedCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.Equal(1, callCount);
// Remove handler.
owner.ControlRemoved -= handler;
affectedControl = child2;
collection.Remove(child2);
Assert.Null(child2.Parent);
Assert.Equal(2, parentChangedCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.Equal(1, callCount);
}
[WinFormsFact]
public void ControlCollection_RemoveAt_Invoke_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2
};
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
object affectedControl = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(affectedControl, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
affectedControl = child2;
collection.RemoveAt(1);
Assert.Equal(new Control[] { child1 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Null(child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove again.
affectedControl = child1;
collection.RemoveAt(0);
Assert.Empty(collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Null(child2.Parent);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void ControlCollection_RemoveAt_InvalidIndexEmpty_ThrowsArgumentOutOfRangeException(int index)
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection.RemoveAt(index));
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(1)]
[InlineData(2)]
public void ControlCollection_RemoveAtInvalidIndexNotEmpty_ThrowsArgumentOutOfRangeException(int index)
{
using Control owner = new();
using Control child = new();
var collection = new Control.ControlCollection(owner)
{
child
};
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection.RemoveAt(index));
}
[WinFormsTheory]
[InlineData("name2")]
[InlineData("NAME2")]
public void ControlCollection_RemoveByKey_InvokeValidKey_ReturnsExpected(string key)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
int layoutCallCount = 0;
child2.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
object affectedControl = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(affectedControl, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
affectedControl = child2;
collection.RemoveByKey(key);
Assert.Equal(new Control[] { child1, child3 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Null(child2.Parent);
Assert.Same(owner, child3.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Remove again.
affectedControl = child3;
collection.RemoveByKey(key);
Assert.Equal(new Control[] { child1 }, collection.Cast<Control>());
Assert.Same(owner, child1.Parent);
Assert.Null(child2.Parent);
Assert.Null(child3.Parent);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsTheory]
[InlineData(null)]
[InlineData("")]
[InlineData("NoSuchName")]
[InlineData("abcd")]
[InlineData("abcde")]
[InlineData("abcdef")]
public void ControlCollection_RemoveByKey_InvokeNoSuchKey_ReturnsNull(string key)
{
using Control owner = new();
using Control child1 = new()
{
Name = "name1"
};
using Control child2 = new()
{
Name = "name2"
};
using Control child3 = new()
{
Name = "name2"
};
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
collection.RemoveByKey(key);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
// Call again.
collection.RemoveByKey(key);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_InvokeChildWithoutHandleOwnerWithoutHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("ChildIndex", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
// Set middle.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Set same.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Set start.
collection.SetChildIndex(child1, 0);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsTheory]
[InlineData(2, 1)]
[InlineData(3, 2)]
[InlineData(4, 2)]
public void ControlCollection_SetChildIndex_InvokeLargeIndex_Success(int index, int expectedParentLayoutCallCount)
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
var collection = new Control.ControlCollection(owner)
{
child1,
child2,
child3
};
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("ChildIndex", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
// Set middle.
collection.SetChildIndex(child1, index);
Assert.Equal(new Control[] { child2, child3, child1 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Set same.
collection.SetChildIndex(child1, index);
Assert.Equal(new Control[] { child2, child3, child1 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(expectedParentLayoutCallCount, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_InvokeChildWithHandleOwnerWithoutHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
collection.Add(child3);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("ChildIndex", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
Assert.NotEqual(IntPtr.Zero, child1.Handle);
int invalidatedCallCount = 0;
child1.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
child1.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
child1.HandleCreated += (sender, e) => createdCallCount++;
try
{
// Set middle.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Set same.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
// Set start.
collection.SetChildIndex(child1, 0);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.False(child2.IsHandleCreated);
Assert.False(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_InvokeChildWithHandleOwnerWithHandle_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
using Control child3 = new();
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
collection.Add(child3);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("ChildIndex", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int invalidatedCallCount = 0;
child1.Invalidated += (sender, e) => invalidatedCallCount++;
int styleChangedCallCount = 0;
child1.StyleChanged += (sender, e) => styleChangedCallCount++;
int createdCallCount = 0;
child1.HandleCreated += (sender, e) => createdCallCount++;
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
try
{
// Set middle.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
// Set same.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
// Set start.
collection.SetChildIndex(child1, 0);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.True(child1.IsHandleCreated);
Assert.Equal(0, invalidatedCallCount);
Assert.Equal(0, styleChangedCallCount);
Assert.Equal(0, createdCallCount);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_InvokeChildWithoutHandleOwnerWithHandle_Success()
{
using Control owner = new();
using SubControl child1 = new();
using Control child2 = new();
using Control child3 = new();
Control.ControlCollection collection = owner.Controls;
collection.Add(child1);
collection.Add(child2);
collection.Add(child3);
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("ChildIndex", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
Assert.NotEqual(IntPtr.Zero, owner.Handle);
int parentInvalidatedCallCount = 0;
owner.Invalidated += (sender, e) => parentInvalidatedCallCount++;
int parentStyleChangedCallCount = 0;
owner.StyleChanged += (sender, e) => parentStyleChangedCallCount++;
int parentCreatedCallCount = 0;
owner.HandleCreated += (sender, e) => parentCreatedCallCount++;
try
{
// Set middle.
child1.DestroyHandle();
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.False(child1.IsHandleCreated);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
// Set same.
collection.SetChildIndex(child1, 1);
Assert.Equal(new Control[] { child2, child1, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(1, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.False(child1.IsHandleCreated);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
// Set start.
collection.SetChildIndex(child1, 0);
Assert.Equal(new Control[] { child1, child2, child3 }, collection.Cast<Control>());
Assert.Equal(0, layoutCallCount);
Assert.Equal(2, parentLayoutCallCount);
Assert.True(owner.IsHandleCreated);
Assert.Equal(0, parentInvalidatedCallCount);
Assert.Equal(0, parentStyleChangedCallCount);
Assert.Equal(0, parentCreatedCallCount);
Assert.False(child1.IsHandleCreated);
Assert.True(child2.IsHandleCreated);
Assert.True(child3.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_NullChild_ThrowsArgumentNullException()
{
using Control owner = new();
var collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentNullException>("child", () => collection.SetChildIndex(null, 0));
}
[WinFormsFact]
public void ControlCollection_SetChildIndex_InvalidIndex_ThrowsArgumentOutOfRangeException()
{
using Control owner = new();
using Control child = new();
var collection = new Control.ControlCollection(owner)
{
child
};
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection.SetChildIndex(child, -2));
}
[WinFormsFact]
public void ControlCollection_IListAdd_Invoke_Success()
{
using Control owner = new();
using Control control1 = new();
using Control control2 = new();
IList collection = owner.Controls;
int parentLayoutCallCount = 0;
string affectedProperty = null;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(collection.Cast<Control>().Last(), e.AffectedControl);
Assert.Equal(affectedProperty, e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
int layoutCallCount1 = 0;
control1.Layout += (sender, e) => layoutCallCount1++;
int layoutCallCount2 = 0;
control2.Layout += (sender, e) => layoutCallCount2++;
try
{
affectedProperty = "Parent";
Assert.Equal(0, collection.Add(control1));
Assert.Same(control1, Assert.Single(collection));
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(control1, Assert.Single(owner.Controls));
Assert.Equal(0, layoutCallCount1);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
// Add another.
affectedProperty = "Parent";
Assert.Equal(1, collection.Add(control2));
Assert.Equal(new Control[] { control1, control2 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Equal(new Control[] { control1, control2 }, owner.Controls.Cast<Control>());
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(2, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
// Add existing.
affectedProperty = "ChildIndex";
Assert.Equal(1, collection.Add(control1));
Assert.Equal(new Control[] { control2, control1 }, collection.Cast<Control>());
Assert.Same(owner, control1.Parent);
Assert.Equal(0, control1.TabIndex);
Assert.Same(owner, control2.Parent);
Assert.Equal(1, control2.TabIndex);
Assert.Equal(new Control[] { control2, control1 }, owner.Controls.Cast<Control>());
Assert.Equal(0, layoutCallCount1);
Assert.Equal(0, layoutCallCount2);
Assert.Equal(3, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(control1.IsHandleCreated);
Assert.False(control2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_IListAdd_NotControl_ThrowsArgumentException()
{
using Control owner = new();
IList collection = new Control.ControlCollection(owner);
Assert.Throws<ArgumentException>("control", () => collection.Add(new object()));
Assert.Throws<ArgumentException>("control", () => collection.Add(null));
}
[WinFormsFact]
public void ControlCollection_IListRemove_Invoke_Success()
{
using Control owner = new();
using Control child1 = new();
using Control child2 = new();
IList collection = new Control.ControlCollection(owner)
{
child1,
child2
};
int layoutCallCount = 0;
child1.Layout += (sender, e) => layoutCallCount++;
int parentLayoutCallCount = 0;
void parentHandler(object sender, LayoutEventArgs e)
{
Assert.Same(owner, sender);
Assert.Same(child1, e.AffectedControl);
Assert.Equal("Parent", e.AffectedProperty);
parentLayoutCallCount++;
}
owner.Layout += parentHandler;
try
{
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove again.
collection.Remove(child1);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
// Remove null.
collection.Remove(null);
Assert.Equal(new Control[] { child2 }, collection.Cast<Control>());
Assert.Null(child1.Parent);
Assert.Same(owner, child2.Parent);
Assert.Equal(1, parentLayoutCallCount);
Assert.False(owner.IsHandleCreated);
Assert.False(child1.IsHandleCreated);
Assert.False(child2.IsHandleCreated);
}
finally
{
owner.Layout -= parentHandler;
}
}
[WinFormsFact]
public void ControlCollection_IListRemove_NotControl_ThrowsArgumentException()
{
using Control owner = new();
IList collection = new Control.ControlCollection(owner);
collection.Remove(new object());
collection.Remove(null);
}
private class CustomLayoutEngineControl : Control
{
private LayoutEngine _layoutEngine;
public CustomLayoutEngineControl()
{
_layoutEngine = new Control().LayoutEngine;
}
public void SetLayoutEngine(LayoutEngine layoutEngine)
{
_layoutEngine = layoutEngine;
}
public override LayoutEngine LayoutEngine => _layoutEngine;
public new void InitLayout() => base.InitLayout();
}
private class SubControl : Control
{
public new void DestroyHandle() => base.DestroyHandle();
public new void SetTopLevel(bool value) => base.SetTopLevel(value);
}
}
|