Index: Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj
===================================================================
diff -u -r3a8bff057967bdb42389382472f6ce55789a0ced -rd7ef66291b1a64881d4e26b8fc30c5f66f16d67a
--- Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj (.../Core.Common.Gui.csproj) (revision 3a8bff057967bdb42389382472f6ce55789a0ced)
+++ Core/Common/src/Core.Common.Gui/Core.Common.Gui.csproj (.../Core.Common.Gui.csproj) (revision d7ef66291b1a64881d4e26b8fc30c5f66f16d67a)
@@ -131,9 +131,7 @@
-
-
Index: Core/Common/src/Core.Common.Gui/PropertyBag/DynamicPropertyBag.cs
===================================================================
diff -u -r9838de527f1f407574730b4e4c04c0982773f9c9 -rd7ef66291b1a64881d4e26b8fc30c5f66f16d67a
--- Core/Common/src/Core.Common.Gui/PropertyBag/DynamicPropertyBag.cs (.../DynamicPropertyBag.cs) (revision 9838de527f1f407574730b4e4c04c0982773f9c9)
+++ Core/Common/src/Core.Common.Gui/PropertyBag/DynamicPropertyBag.cs (.../DynamicPropertyBag.cs) (revision d7ef66291b1a64881d4e26b8fc30c5f66f16d67a)
@@ -17,19 +17,31 @@
{
///
/// Instantiates a new instance of , wrapping another
- /// object an exposing properties for that object.
+ /// object and exposing properties for that object.
///
/// The object to be wrapped.
+ /// This class makes sure the following special attributes on properties are processed:
+ ///
+ ///
+ ///
+ ///
+ ///
public DynamicPropertyBag(object propertyObject)
{
- Properties = new PropertySpecCollection();
- Initialize(propertyObject);
+ Properties = new HashSet();
+ WrappedObject = propertyObject;
+
+ foreach (var propertyInfo in propertyObject.GetType().GetProperties()
+ .OrderBy(x => x.MetadataToken))
+ {
+ Properties.Add(new PropertySpec(propertyInfo));
+ }
}
///
/// Gets the collection of properties contained within this .
///
- public PropertySpecCollection Properties { get; private set; }
+ public ICollection Properties { get; private set; }
///
/// Gets the object wrapped inside this
@@ -41,16 +53,6 @@
return WrappedObject.ToString();
}
- private void Initialize(object propertyObject)
- {
- WrappedObject = propertyObject;
-
- foreach (var propertyInfo in propertyObject.GetType().GetProperties().OrderBy(x => x.MetadataToken).ToArray())
- {
- Properties.Add(new PropertySpec(propertyInfo));
- }
- }
-
#region ICustomTypeDescriptor explicit interface definitions
#region Implementations delegated to System.ComponentModel.TypeDescriptor
@@ -80,11 +82,6 @@
return TypeDescriptor.GetDefaultEvent(this, true);
}
- public object GetEditor(Type editorBaseType)
- {
- return TypeDescriptor.GetEditor(this, editorBaseType, true);
- }
-
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
@@ -95,54 +92,58 @@
return TypeDescriptor.GetEvents(this, attributes, true);
}
- public PropertyDescriptorCollection GetProperties()
+ public object GetEditor(Type editorBaseType)
{
- return GetProperties(new Attribute[0]);
+ return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
#endregion
public PropertyDescriptor GetDefaultProperty()
{
- return Properties.Count > 0 ? new PropertySpecDescriptor(Properties[0], WrappedObject) : null;
+ return Properties.Count > 0 ? new PropertySpecDescriptor(Properties.First(), WrappedObject) : null;
}
- public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
+ public PropertyDescriptorCollection GetProperties()
{
- // Rather than passing this function on to the default TypeDescriptor,
- // which would return the actual properties of PropertyBag, I construct
- // a list here that contains property descriptors for the elements of the
- // Properties list in the bag.
- var props = new List();
- var propsToOrder = new List>();
+ return GetProperties(new Attribute[0]);
+ }
- foreach (PropertySpec property in Properties)
- {
- // Create a new property descriptor for the property item, and add it to the list.
- var pd = new PropertySpecDescriptor(property, WrappedObject);
+ public PropertyDescriptorCollection GetProperties(Attribute[] attributesFilter)
+ {
+ var propertyDescriptorsToReturn = Properties.Select(p => new PropertySpecDescriptor(p, WrappedObject))
+ .Where(t => ShouldDescriptorBeReturned(t, attributesFilter));
- var propertyOrderAttribute = property.Attributes != null ? property.Attributes.OfType().FirstOrDefault() : null;
+ var propertySpecDescriptors = OrderPropertyDescriptors(propertyDescriptorsToReturn);
+ return new PropertyDescriptorCollection(propertySpecDescriptors);
+ }
+
+ private static PropertyDescriptor[] OrderPropertyDescriptors(IEnumerable propertyDescriptorsToReturn)
+ {
+ var unorderedProperties = new List();
+ var propertiesWithOrdering = new List>();
+
+ foreach (PropertyDescriptor pd in propertyDescriptorsToReturn)
+ {
+ var propertyOrderAttribute = pd.Attributes.OfType().FirstOrDefault();
if (propertyOrderAttribute != null)
{
- propsToOrder.Add(new Tuple(propertyOrderAttribute.Order, pd));
+ propertiesWithOrdering.Add(new Tuple(propertyOrderAttribute.Order, pd));
}
else
{
- props.Add(pd);
+ unorderedProperties.Add(pd);
}
}
+ var orderedProperties = propertiesWithOrdering.OrderBy(p => p.Item1).Select(p => p.Item2);
- var orderedProperties = propsToOrder.OrderBy(p => p.Item1).Select(p => p.Item2).ToList();
+ return orderedProperties.Concat(unorderedProperties).ToArray();
+ }
- // Convert the list of PropertyDescriptors to a collection that the
- // ICustomTypeDescriptor can use, and return it.
- var browsableAttribute = attributes.OfType().FirstOrDefault();
-
- var propertySpecDescriptors = (browsableAttribute != null)
- ? orderedProperties.Concat(props).Where(p => p.IsBrowsable == browsableAttribute.Browsable)
- : orderedProperties.Concat(props);
-
- return new PropertyDescriptorCollection(propertySpecDescriptors.ToArray());
+ private static bool ShouldDescriptorBeReturned(PropertyDescriptor propertySpecDescriptor, IEnumerable attributesFilter)
+ {
+ var browsableAttribute = attributesFilter.OfType().FirstOrDefault();
+ return browsableAttribute == null || propertySpecDescriptor.IsBrowsable == browsableAttribute.Browsable;
}
public object GetPropertyOwner(PropertyDescriptor pd)
Index: Core/Common/src/Core.Common.Gui/PropertyBag/PropertySpec.cs
===================================================================
diff -u -r8de8647e95dd220a1a4d78980e88af32ee9d2d3f -rd7ef66291b1a64881d4e26b8fc30c5f66f16d67a
--- Core/Common/src/Core.Common.Gui/PropertyBag/PropertySpec.cs (.../PropertySpec.cs) (revision 8de8647e95dd220a1a4d78980e88af32ee9d2d3f)
+++ Core/Common/src/Core.Common.Gui/PropertyBag/PropertySpec.cs (.../PropertySpec.cs) (revision d7ef66291b1a64881d4e26b8fc30c5f66f16d67a)
@@ -44,7 +44,7 @@
/// class, such as
/// and .
///
- public Attribute[] Attributes { get; set; }
+ public Attribute[] Attributes { get; private set; }
///
/// Gets the name of the property.
Fisheye: Tag d7ef66291b1a64881d4e26b8fc30c5f66f16d67a refers to a dead (removed) revision in file `Core/Common/src/Core.Common.Gui/PropertyBag/PropertySpecCollection.cs'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag d7ef66291b1a64881d4e26b8fc30c5f66f16d67a refers to a dead (removed) revision in file `Core/Common/src/Core.Common.Gui/PropertyBag/PropertySpecEventArgs.cs'.
Fisheye: No comparison available. Pass `N' to diff?
Index: Core/Common/test/Core.Common.Gui.Test/PropertyBag/DynamicPropertyBagTest.cs
===================================================================
diff -u -r8de8647e95dd220a1a4d78980e88af32ee9d2d3f -rd7ef66291b1a64881d4e26b8fc30c5f66f16d67a
--- Core/Common/test/Core.Common.Gui.Test/PropertyBag/DynamicPropertyBagTest.cs (.../DynamicPropertyBagTest.cs) (revision 8de8647e95dd220a1a4d78980e88af32ee9d2d3f)
+++ Core/Common/test/Core.Common.Gui.Test/PropertyBag/DynamicPropertyBagTest.cs (.../DynamicPropertyBagTest.cs) (revision d7ef66291b1a64881d4e26b8fc30c5f66f16d67a)
@@ -1,7 +1,7 @@
using System;
using System.ComponentModel;
+using System.Drawing.Design;
using System.Linq;
-using System.Windows.Forms;
using Core.Common.Gui.Attributes;
using Core.Common.Gui.PropertyBag;
@@ -51,43 +51,169 @@
var dynamicPropertyBag = new DynamicPropertyBag(propertyObject);
// Assert
- var namePropertySpec = dynamicPropertyBag.Properties.OfType().First(ps => ps.Name == "Name");
- Assert.IsTrue(namePropertySpec.Attributes.Any(a => a is System.ComponentModel.CategoryAttribute));
+ var namePropertySpec = dynamicPropertyBag.Properties.First(ps => ps.Name == "Name");
+ CollectionAssert.Contains(namePropertySpec.Attributes, new System.ComponentModel.CategoryAttribute("General"),
+ "Should have initialized Attributes of the property spec with declared Category(\"General\").");
- var descriptionPropertySpec = dynamicPropertyBag.Properties.OfType().First(ps => ps.Name == "Description");
+ var descriptionPropertySpec = dynamicPropertyBag.Properties.First(ps => ps.Name == "Description");
CollectionAssert.Contains(descriptionPropertySpec.Attributes, ReadOnlyAttribute.Yes,
"Should have initialized Attributes of the property spec with declared ReadOnlyAttribute.");
}
[Test]
- public void GivenClassWithDynamicReadOnlyAttribute_WhenNotReadOnly_ThenTypeDescriptorDoesNotHaveReadOnlyAttribute()
+ public void ToString_ReturnToStringFromWrappedObject()
{
// Setup
- var testProperties = new TestProperties
- {
- IsNameReadOnly = false
- };
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
- // Precondition
- var namePropertyAttributes = testProperties.GetType().GetProperty("Name").GetCustomAttributes(true);
- Assert.IsFalse(namePropertyAttributes.Any(a => a is ReadOnlyAttribute));
- CollectionAssert.Contains(namePropertyAttributes, new DynamicReadOnlyAttribute());
- Assert.IsFalse(testProperties.DynamicReadOnlyValidationMethod("Name"));
+ // Call
+ var text = dynamicPropertyBag.ToString();
+ // Assert
+ Assert.AreEqual(target.ToString(), text);
+ }
+
+ [Test]
+ public void GetAttributes_Always_ReturnEmpty()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
// Call
- var dynamicPropertyBag = new DynamicPropertyBag(testProperties);
+ var attributes = dynamicPropertyBag.GetAttributes();
// Assert
- PropertyDescriptorCollection propertyDescriptorCollection = dynamicPropertyBag.GetProperties();
- PropertyDescriptor namePropertyDescriptor = propertyDescriptorCollection.Find("Name", false);
+ CollectionAssert.IsEmpty(attributes);
+ }
- CollectionAssert.Contains(namePropertyDescriptor.Attributes, new DynamicReadOnlyAttribute(),
- "DynamicReadOnlyAttribute declared on Name property should also be present on PropertyDescriptor.");
- Assert.IsFalse(namePropertyDescriptor.Attributes.OfType().Any(a => a is ReadOnlyAttribute),
- "As Name property has no ReadOnlyAttribute nor does DyanmicReadOnlyValidationMethod evaluate to true, no ReadOnlyAttribute should be on PropertyDescriptor.");
+ [Test]
+ public void GetClassName_Always_ReturnDynamicPropertyBagClassName()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var className = dynamicPropertyBag.GetClassName();
+
+ // Assert
+ Assert.AreEqual(dynamicPropertyBag.GetType().FullName, className);
}
[Test]
+ public void GetComponentName_Always_ReturnNull()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var componentName = dynamicPropertyBag.GetComponentName();
+
+ // Assert
+ Assert.IsNull(componentName);
+ }
+
+ [Test]
+ public void GetConverter_Always_ReturnDefaultTypeConverter()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var typeConverter = dynamicPropertyBag.GetConverter();
+
+ // Assert
+ Assert.AreEqual(TypeDescriptor.GetConverter(dynamicPropertyBag, true), typeConverter);
+ }
+
+ [Test]
+ public void GetDefaultEvent_Always_ReturnNull()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var eventDescriptor = dynamicPropertyBag.GetDefaultEvent();
+
+ // Assert
+ Assert.IsNull(eventDescriptor);
+ }
+
+ [Test]
+ public void GetEvents_Always_ReturnEmpty()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var events = dynamicPropertyBag.GetEvents();
+
+ // Assert
+ CollectionAssert.IsEmpty(events);
+ }
+
+ [Test]
+ public void GetEventsParametered_Always_ReturnEmpty()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var events = dynamicPropertyBag.GetEvents(new Attribute[0]);
+
+ // Assert
+ CollectionAssert.IsEmpty(events);
+ }
+
+ [Test]
+ public void GetEditor_Always_ReturnNull()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var editor = dynamicPropertyBag.GetEditor(typeof(UITypeEditor));
+
+ // Assert
+ Assert.IsNull(editor);
+ }
+
+ [Test]
+ public void GetDefaultProperty_ObjectHasNotProperties_ReturnNull()
+ {
+ // Setup
+ var dynamicPropertyBag = new DynamicPropertyBag(new object());
+
+ // Call
+ var defaultProperty = dynamicPropertyBag.GetDefaultProperty();
+
+ // Assert
+ Assert.IsNull(defaultProperty);
+ }
+
+ [Test]
+ public void GetDefaultProperty_ObjectWithProperties_ReturnFirstFromProperties()
+ {
+ // Setup
+ var target = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(target);
+
+ // Call
+ var defaultProperty = dynamicPropertyBag.GetDefaultProperty();
+
+ // Assert
+ Assert.AreEqual(dynamicPropertyBag.Properties.First().Name, defaultProperty.Name);
+ }
+
+ [Test]
public void DynamicPropertyBagResolvesDynamicVisibleAttributes()
{
var propertyObject = new TestProperties
@@ -116,68 +242,190 @@
}
[Test]
- public void DynamicPropertyBagMaintainsDesiredOrdering()
+ public void GetProperties_SomePropertiesWithOrderAttribute_ReturnElementsInDesiredOrdering()
{
+ // Setup
var dynamicPropertyBag = new DynamicPropertyBag(new TestOrderedProperties());
- var propertyDescriptorCollection = ((ICustomTypeDescriptor) dynamicPropertyBag).GetProperties();
+ // Call
+ var propertyDescriptorCollection = dynamicPropertyBag.GetProperties();
- Assert.AreEqual("Name", propertyDescriptorCollection[3].DisplayName);
- Assert.AreEqual("Description", propertyDescriptorCollection[2].DisplayName);
- Assert.AreEqual("PropOne", propertyDescriptorCollection[1].DisplayName);
- Assert.AreEqual("PropTwo", propertyDescriptorCollection[0].DisplayName);
+ // Assert
+ var index = 0;
+ Assert.AreEqual("PropTwo", propertyDescriptorCollection[index++].DisplayName);
+ Assert.AreEqual("PropOne", propertyDescriptorCollection[index++].DisplayName);
+ Assert.AreEqual("Description", propertyDescriptorCollection[index++].DisplayName);
+ Assert.AreEqual("Name", propertyDescriptorCollection[index++].DisplayName);
+
+ var propThreeDescriptor = propertyDescriptorCollection.Find("PropThree", false);
+ Assert.GreaterOrEqual(propertyDescriptorCollection.IndexOf(propThreeDescriptor), index,
+ "PropThree is not decorated with PropertyOrderAttribute, therefore should come after those that are.");
+ var propFourDescriptor = propertyDescriptorCollection.Find("PropFour", false);
+ Assert.GreaterOrEqual(propertyDescriptorCollection.IndexOf(propFourDescriptor), index,
+ "PropFour is not decorated with PropertyOrderAttribute, therefore should come after those that are.");
}
[Test]
public void DynamicPropertyBagWrapsNestedPropertyObjects()
{
- var subProperties = new TestProperties()
+ // Setup
+ var subProperties = new TestProperties
{
Name = "test"
};
- var testProperties = new TestWithNestedPropertiesClassProperties()
+ var testProperties = new TestWithNestedPropertiesClassProperties
{
SubProperties = subProperties
};
var dynamicPropertyBag = new DynamicPropertyBag(testProperties);
- var propertiesCollection = ((ICustomTypeDescriptor) dynamicPropertyBag).GetProperties();
+ var propertiesCollection = dynamicPropertyBag.GetProperties();
+
+ // Call
var wrappedValue = propertiesCollection[0].GetValue(dynamicPropertyBag.WrappedObject);
- // check the object properties are wrapped in a dynamic property bag
- Assert.IsInstanceOf(wrappedValue, "Object properties wrapped in dynamic property bag");
+ // Assert
+ var bag = (DynamicPropertyBag)wrappedValue;
+ Assert.AreSame(subProperties, bag.WrappedObject);
}
[Test]
- public void DynamicPropertyBagPropagatesValueSetter()
+ public void GivenPropertyDescriptorFromDynamicPropertyBag_WhenSettingProperty_ThenWrappedObjectUpdated()
{
- var propertyGrid = new PropertyGrid();
-
+ // Setup
var testProperties = new TestProperties
{
Name = "name"
};
var dynamicPropertyBag = new DynamicPropertyBag(testProperties);
- propertyGrid.SelectedObject = dynamicPropertyBag;
+ var newName = "newName";
- var expected = "newName";
- propertyGrid.SelectedGridItem.PropertyDescriptor.SetValue(testProperties, expected);
+ // Call
+ dynamicPropertyBag.GetProperties()["Name"].SetValue(testProperties, newName);
- Assert.AreEqual(expected, testProperties.Name, "Name not correctly set");
+ // Assert
+ Assert.AreEqual(newName, testProperties.Name);
}
[Test]
- public void PropertyWithNoSetterAreReadOnly()
+ public void GivenPropertiesWithoutPublicSetter_WhenGettingPropertyDescriptors_ThenPropertiesDecoratedWithReadOnlyAttribute()
{
+ // Setup
var dynamicPropertyBag = new DynamicPropertyBag(new TestWithoutSetterPropertyClassProperties());
- var propertyDescriptorCollection = ((ICustomTypeDescriptor) dynamicPropertyBag).GetProperties();
- //check both properties have the readonly attribute
- Assert.IsTrue(propertyDescriptorCollection[0].Attributes.Matches(new ReadOnlyAttribute(true)));
- Assert.IsTrue(propertyDescriptorCollection[1].Attributes.Matches(new ReadOnlyAttribute(true)));
+ // Call
+ var propertyDescriptorCollection = dynamicPropertyBag.GetProperties();
+
+ // Assert
+ Assert.IsTrue(propertyDescriptorCollection[0].Attributes.Matches(ReadOnlyAttribute.Yes));
+ Assert.IsTrue(propertyDescriptorCollection[1].Attributes.Matches(ReadOnlyAttribute.Yes));
}
+ [Test]
+ public void GetProperties_RepeatedCallForSameState_RetainSameElementOrderAndContents()
+ {
+ // Setup
+ var propertyObject = new TestOrderedProperties();
+
+ var dynamicPropertyBag = new DynamicPropertyBag(propertyObject);
+
+ var originalProperties = dynamicPropertyBag.GetProperties();
+
+ // Call
+ for (int i = 0; i < 100; i++)
+ {
+ var currentProperties = dynamicPropertyBag.GetProperties();
+
+ // Assert
+ CollectionAssert.AreEqual(originalProperties, currentProperties);
+ }
+ }
+
+ [Test]
+ public void GetProperties_RepeatedConstructionsForSameState_RetainSameElementOrderAndContents()
+ {
+ // Setup
+ var propertyObject = new TestOrderedProperties();
+
+ var originalProperties = new DynamicPropertyBag(propertyObject).GetProperties();
+
+ // Call
+ for (int i = 0; i < 100; i++)
+ {
+ var currentProperties = new DynamicPropertyBag(propertyObject).GetProperties();
+
+ // Assert
+ CollectionAssert.AreEqual(originalProperties, currentProperties);
+ }
+ }
+
+ [Test]
+ public void GetProperties_BrowsableTrueFilter_ReturnOnlyPropertiesThatAreBrowsable()
+ {
+ // Setup
+ var propertyObject = new TestProperties
+ {
+ Visible = false
+ };
+ var dynamicPropertyBag = new DynamicPropertyBag(propertyObject);
+
+ // Call
+ var properties = dynamicPropertyBag.GetProperties(new Attribute[]
+ {
+ BrowsableAttribute.Yes
+ });
+
+ // Assert
+ Assert.Less(properties.Count, dynamicPropertyBag.Properties.Count);
+ Assert.IsNull(properties.Find("Name", false),
+ "Name is dynamically not browsable, therefore should not be returned.");
+ Assert.IsNotNull(properties.Find("Description", false));
+ Assert.IsNotNull(properties.Find("IsNameReadOnly", false));
+ Assert.IsNull(properties.Find("Visible", false),
+ "Visible is statically not browsable, therefore should not be returned.");
+ }
+
+ [Test]
+ public void GetProperties_BrowsableNoFilter_ReturnOnlyPropertiesThatAreBrowsable()
+ {
+ // Setup
+ var propertyObject = new TestProperties
+ {
+ Visible = false
+ };
+ var dynamicPropertyBag = new DynamicPropertyBag(propertyObject);
+
+ // Call
+ var properties = dynamicPropertyBag.GetProperties(new Attribute[]
+ {
+ BrowsableAttribute.No
+ });
+
+ // Assert
+ Assert.Less(properties.Count, dynamicPropertyBag.Properties.Count);
+ Assert.IsNotNull(properties.Find("Name", false),
+ "Name is dynamically not browsable, therefore should be returned.");
+ Assert.IsNull(properties.Find("Description", false));
+ Assert.IsNull(properties.Find("IsNameReadOnly", false));
+ Assert.IsNotNull(properties.Find("Visible", false),
+ "Visible is statically not browsable, therefore should be returned.");
+ }
+
+ [Test]
+ public void GetPropertyOwner_Always_ReturnWrappedObject()
+ {
+ // Setup
+ var propertyObject = new TestProperties();
+ var dynamicPropertyBag = new DynamicPropertyBag(propertyObject);
+
+ // Call
+ var owner = dynamicPropertyBag.GetPropertyOwner(null);
+
+ // Assert
+ Assert.AreSame(propertyObject, owner);
+ }
+
#region Test Classes
private class TestOrderedProperties
@@ -193,6 +441,10 @@
[PropertyOrder(0)]
public string PropTwo { get; set; }
+
+ public int PropThree { get; set; }
+
+ public int PropFour { get; set; }
}
private class TestWithNestedPropertiesClassProperties
@@ -219,8 +471,10 @@
[System.ComponentModel.Category("General")]
public string Name { get; set; }
+ [Browsable(true)]
public bool IsNameReadOnly { get; set; }
+ [Browsable(false)]
public bool Visible { get; set; }
[ReadOnly(true)] //one static property
@@ -244,6 +498,11 @@
{
return Visible;
}
+
+ public override string ToString()
+ {
+ return Name;
+ }
}
private class TestWithoutSetterPropertyClassProperties