Looking for generic method to access a components form


G

Guest

Hi,

While trying to explain what I want to achieve, this
message is getting longer and longer, so maybe it's
better to ask without explaining first.

So let's start with a short version:

A custom user control has a collection derived from
CollectionBase. That collection consists of instances of
a custom class derived from Component (so it can
be edited easily using a property editor, wich, in this
case, includes a 'component picker').

Is it possible, when editing such a collection item in
the Visual Studio designer, to find all the way back to
the form holding the control, without using any sorts
of typecasts to anything but default .net classes?

Note that the collection items are being edited
with a selection editor derived from
ObjectSelectorEditor and I want to try to keep the
code as generic as possible so it can be reused for
other yet-to-be-build controls.



long version:

I've been busy with a custom control derived from
UserControl called: LayeredGrid.

This custom contol has a collection property containing
a list of instances to a class called GridLayer.

This GridLayer class has a property to store a reference to
an ImageList.

I want to be able to select one of the image lists a developer
placed on the same form (container?) as where he/she
placed the LayeredGrid.

Already have a working image list selector, derived from
ObjectSelectorEditor and tested it out using an ImageList
property in the LayeredGrid control. So far so good.

Using (context.Instance as Control).FindForm() I can find
the form on which the LayeredGrid is placed and, using
its container, I can find and filter the list of components.
Like this:

Form f = (context.Instance as Control).FindForm();
foreach (Component comp in f.Container.Components)
{
if (comp is ImageList)
selector.AddNode(
(comp as ImageList).Site.Name, comp, null);
}

The problem is, if I want to have an ImageList property
in the collection item class, the collection items don't have
any reference to the control owning the collection unless
I program it myself using an 'owner' property of some
sort.

That works, but now, the ImageListSelector needs to
know the type of the collection item so it can use it in
a cast and access the 'owner' property to find the way
back to the LayerdGrid instance before it can call
FindForm() again.

This is the custom object selector used to show a list of
available ImageList components:

internal class ImageListSelectionEditor
: ObjectSelectorEditor
{
protected override void FillTreeWithData(
ObjectSelectorEditor.Selector selector,
ITypeDescriptorContext context,
IServiceProvider provider)
{
// Clear the selection
base.FillTreeWithData(selector, context, provider);

// Add the '(none)' item.
selector.AddNode("(none)", null, null);

// Add all ImageList components of the form's container.
if (context.Instance != null)
{
Form f = null;

if (context.Instance is GridLayer) // <<< I don't want to do
this.
{
// MessageBox.Show(
// (context.Instance as
GridLayer).Owner.ToString());
f = (context.Instance as GridLayer).Owner.FindForm(); //
<<< Yuk!
}
else
{
// This will works for all user controls IF the
// property is part of the control itself.
f = (context.Instance as Control).FindForm();
}

if (f != null)
{
foreach (Component comp in f.Container.Components)
{
if (comp is ImageList)
selector.AddNode(
(comp as ImageList).Site.Name, comp, null);
}
}
}
}

I also tried getting to the form using context.Container,
context.Instance.Container, and several other things. But nothing
seems to point back to the GridLayer control or to the form.

pff, I hope this was clear enough to explain the problem.

I've been googling a lot for this but it seems that there isn't
much to read on user controls and, especially, custom property
editors. Although there are some examples about the basic
aspects, I haven't been able to find anything describing
collections with 'component pickers'.


Best regards,
Marcel
 
Ad

Advertisements

M

Marcel Overweel

Hi,

While trying to explain what I want to achieve, this
message is getting longer and longer, so maybe it's
better to ask without explaining first.

So let's start with a short version:

A custom user control has a collection derived from
CollectionBase. That collection consists of instances of
a custom class derived from Component (so it can
be edited easily using a property editor, wich, in this
case, includes a 'component picker').

Is it possible, when editing such a collection item in
the Visual Studio designer, to find all the way back to
the form holding the control, without using any sorts
of typecasts to anything but default .net classes?

Note that the collection items are being edited
with a selection editor derived from
ObjectSelectorEditor and I want to try to keep the
code as generic as possible so it can be reused for
other yet-to-be-build controls.



long version:
(snipperdesnip)

Best regards,
Marcel


OK, got it!
It's just soooo easy, can't understand I didn't see it
yesterday.. LOL!

This is all that's needed to get the form from within
any location (property/collection item/whatever):

Form f = (
(context.Instance as Component).Container
as System.ComponentModel.Design.IDesignerHost
).RootComponent as Form;

And that works for both properties from the control itself
and properties inside any of the collection items.

Need to add some type and null checks to make the code
safe and clean. But that was it.


Best regards,
Marcel

(sorry for the postname mixup, my newsreader was
reverted back to default settings or something.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top