Reputation: 185
I have a user control that has a property that is a list of a custom object type. When I create a custom class by inheriting from List<>, it mostly works:
public class CustomCol : List<CustomItem> {
// ...
}
I'm then able to implement the property in the user control something like this:
CustomCol _items = new CustomCol();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public CustomCol Items
{
get { return _items; }
}
This makes it behave as I would expect it to. I'm able to click the ellipsis button in the Designer, and it brings up the CollectionEditor, and adding items correctly adds CustomItems.
Unfortunately, this method doesn't allow me to detect when items are added, deleted, or modified in the CollectionEditor. After considerable research, I discovered that this is because the designer editor calls IList.Add() to add new items, and this is not overridable, so I cannot intercept those calls without implementing my own collection class from the ground up that implements IList.
So that is exactly what I tried to do. The code I attempted looked something like this:
public class CustomCol: System.Collections.IList
{
private List<CustomItem> = new List<CustomItem>();
int System.Collections.IList.Add(Object value)
{
_items.Add((CustomItem)value);
return _items.Count;
}
// All of the other IList methods are similarly implemented.
}
Before going any further, I already see a problem. The CollectionEditor is going to be passing generic System.Objects, rather than my CustomItem class.
So the next thing I tried was implementing IList instead, as such:
public class CustomCol: IList<CustomClass>
{
private List<CustomItem> = new List<CustomItem>();
void ICollection<CustomItem>.Add(NameValueItem item)
{
_items.Add(item);
}
// All of the other IList methods are similarly implemented.
}
In theory, this works, but I can't get the CollectionEditor to launch in the designer at all. I've been working on this all day, looking for solutions online, experimenting trying to understand how all this works. At this point I have a very severe headache, and am looking for any kind of guidance.
To summarize: I want to create a user control with a property that is a custom collection class that I can edit in the Designer using the CollectionEditor (or something equivalent) and I need to know when those designer changes are made so that I can update the appearance of the control.
Upvotes: 2
Views: 1581
Reputation: 3497
You can implement your custom collection the way the framework's collections do it. Don't look too much.
Implement the non generic IList as usual but make the implemented methods private. Then add an another public method for each one of the implemented methods, but this time these public methods will accept the custom type you want. These methods will be called from the implemented private methods with a type cast.
This is the way the framework's collections follow. Have a look at the UIElementCollection class. You'll see the exact same implementation.
Example for the IList.Add method:
Suppose the custom class is called TextElement
.
private int IList.Add(object value)
{
return Add((TextElement)value);
}
public int Add(TextElement element)
{
[Your custom logic here]
}
Edit:
You can't just implicitly implement an interface using private methods. You'll have to explicitly do that. For example you'll need to do a private int IList.Add
instead of private int Add
, and private void ICollection.CopyTo
instead of private void CopyTo
for all of this to work.
Upvotes: 1