views:

808

answers:

7

Hi, I have a custom user control. Normally it inherites the UserControl class. But by this way it inherites all the public methods and properties of UserControl. But I want to hide all these and implement my own few methods and properties.

Say that I have a custom control named CustomControl.

public class CustomControl : UserControl

When I create an instance of CustomControl:

CustomControl cControl = new CustomControl();

When I type cControl. intellisense offers me all the methods and properties derived from UserControl. But I want to list only mine which are implemented in CustomControl class.

Thank you

+1  A: 

Why not use composition and make the UserControl a member of your custom control instead of inheriting from it?

Wil P
He wouldn't get designer support out of the box, which is one reason.
Neil Barnwell
Yea, good point. As others have suggested it might be a good idea to encapsulate those methods in an interface and access the control via a reference to the interface than the CustomControl itself.
Wil P
Neil is right, I need designer support
UnforgivenX
Cool - As the others suggest I would just make a interface that encapsulates the methods you want and implement that interface on your custom control. Then just reference the control using the interface you've defined within the scope of the code that you want to have a limited set of members.
Wil P
But with interface, I can not use my custom control by dragging and dropping it in a form in the design view since it will be created with "CustomControl" itself instead of the interface. I need to go to designer codes and change "CustomControl" to "ICustomControl" manually.
UnforgivenX
why does it matter if it's in the designer code?
Richard Hein
You are still dragging an instance of the user control onto the design surface, not the interface. Using the interface in your code to reference the control would limit the to the methods and properties defined within the interface. Richard's code and reply demonstrates what I am talking about.
Wil P
Richard, I'm trying to develop a usercontrol which is able to plot some given functions. When I distribute this, I do not want to make any user, after dragging the control from toolbox, go and edit the designer code.
UnforgivenX
A: 

Don't inherit UserControl, inherit Control instead.

Neil Barnwell
It loses designer GUI I think with this way
UnforgivenX
+1  A: 

You can hide them from IntelliSense by shadowing them in your class (redeclaring each inherited method with keyword new), and applying EditorBrowsableAttribute to them. But the methods will still be there, and will still be callable. In general, there is no way to disallow clients to call inherited methods on instances of your class.

Pavel Minaev
But UserControl class has so many properties and methods. I can not hide them all using "private new". It would cost me a day
UnforgivenX
Sorry, it is as good as it gets. If you really want to go that way, you can make your class partial, and auto-generate the part with `new` using Reflection on `UserControl` and CodeDOM.
Pavel Minaev
+4  A: 

That's not how inheritance works. By creating a sub class you are explicitly saying you want all of the base class's methods and properties accessible.

ChrisF
The whole point of `UserControl` is to give designer support, and that requires inheritance.
Pavel Minaev
Exactly as Pavel said
UnforgivenX
I agree to you chris, that I'm saying that "I want all of the base class's methods and properties accessible". The problem is that sometimes you only say that because you aren't given any alternative.
Ciwee
Yes, I could not find ant alternative. I need the designer and hide the inherited methods
UnforgivenX
+6  A: 

You could make an interface, and then only the methods and properties of the interface will be exposed.

public interface ICustomControl {
     string MyProperty { get; set;}
}

public class CustomControl : UserControl, ICustomControl {
     public string MyProperty { get; set; }
}

...

ICustomControl cControl = new CustomControl();

Then intellisense only shows MyProperty and Object's members (and extension methods, if any apply).

EDIT:

protected ICustomControl CustomControl { get; set; }
    public Form1()
    {
        InitializeComponent();
        CustomControl = this.customControl1;
        CustomControl.MyProperty = "Hello World!"; // Access everything through here.
    }

Then you can make CustomControl's scope internal or protected internal if you want.

Richard Hein
Very cunning...
Philip Wallace
Intresting way. At the end it does the job in expense of extra code block and having used "ICustomControl" instead of simply "CustomControl"
UnforgivenX
I'm used to doing that, because if you are making a UserControl ComVisible, but use AutoDual then you'll expose properties/methods that cannot be exported ... more info about that at http://msdn.microsoft.com/en-us/library/ms182205(VS.80).aspx. So the correct way (in C# ... VB has a shortcut, the ComClass attribute, which is another option), is to explicitly create an interface as the example in the link shows.
Richard Hein
But with this way, I can not use my custom control by dragging and dropping it in a form in the design view since it will be created with "CustomControl" itself instead of the interface. I need to go to designer codes and change "CustomControl" to "ICustomControl" manually.
UnforgivenX
I updated my answer to explain
Richard Hein
The only time you'd ever see anything other than the member you want is a) in CustomControl, b) in the host control's designer code, c) in your assignment to your property which returns the interface, d) in inheriting controls, if you allow that, but you can prevent that using the scope declarations.
Richard Hein
I could not get the point. How this will be a solution to dragging and dropping issue? When I drag my control from the toolbox onto the Form, I will have to add extra codes to be able to use the interface. Is there any way to create an Interface instance by dragging and dropping from the toolbox?
UnforgivenX
What dragging and dropping issue are you having? You drag a CustomControl to your Form, then create a property that returns ICustomControl and references the control you dropped on the form. It's 2 lines of code to define the property and instantiate it, it can't get any simpler. You can't create an instance of an interface, by definition. You just access customControl through ICustomControl, by returning customControl as an ICustomControl.
Richard Hein
A: 

You could do this through aggregation e.g.

public CustomControl
{
    private Control control_;
    public property control {get{ return _control;}}
    .
    .
    .
    public void FunctionIWantExposed() {}
}

But this isn't particularly helpful. You won't be able to add it to any controls collection. You could use the property in the custom class control and add that to a controlscollection but then all those methods you are trying to hide get exposed again.

Dustin Hodges
+1  A: 

You have some options:

  1. Using EditorBrowsableAttribute will hide the properties from intellisense
  2. Using BrowsableAttribute will hide the properties from property grids
  3. Hiding the properties themselves using "private new" will hide them from everything

Things to consider:

  1. Using attributes will hide the properties depending on the implementation of the "consumer" but in a language level, you aren't hiding anything. For instance, you could implement a property grid that checks for EditorBrowsableAttribute before showing the property. [I'm not sure about Microsoft's Windows Forms implementation]
  2. Using "private new" will also prevent you to access the properties, although, inside your control you can yet call base.PropertyName to have access to the original ones.

I understand your intention. It's usual to restrict behavior of enherited controls even though it "breaks" the inheritance concept.

Ciwee
But UserControl class has so many properties and methods. I can not hide them all using "private new"
UnforgivenX
@UnforgivenX: Unfortunately it isn't possible to hide all properties of a class at once.
Ciwee
Thank you though
UnforgivenX