26

In the Visual Studio form designer, you can add an event handler on the Properties window in the "Events" list by double-clicking it. You can also add an event handler — at least in VB.NET — in the code view by selecting the associated "Events" item in the left-hand drop-down and then the desired event in the right-hand drop-down. My question is: how is it that some events that are only available via the latter technique and not the former? For example, the HandleCreated event is available in the code view:

enter image description here

But not in the designer:

enter image description here

This is fine in VB.NET because I can always use the first technique to quickly generate the event handlers. However, in C#, the first technique is not possible, yet the problem still exists; that is, some events are not present in the designer list in the Properties window. The only other way I know of creating the event handler is to manually add it, which includes manually wiring up the event handler.

Is there something technical that makes it so that some events are missing from the designer Events list in the Properties window? Given that that is true, how can I quickly generate event handlers in C# like I can in VB.NET?

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • 7
    I didn't down-vote it but I suspect the reason is because you seem to be asking "why" rather than "how". "How" is a good question. "Why" is more subjective and opinion-based (short of some sort of official documentation of the reasoning, that is). – Steven Doggart Mar 26 '15 at 14:27
  • Okay, I've updated my question slightly, because I'd still like to know how it's done in C# other than manually. – rory.ap Mar 26 '15 at 14:29
  • @StevenDoggart -- I see a lot of questions with quite a few up votes and no down votes that ask why. I just came across one today: http://stackoverflow.com/questions/1359948/why-doesnt-stringbuilder-have-indexof-method. So, I still don't quite understand the down votes here. – rory.ap Mar 27 '15 at 13:43
  • I know. Like I said, I wasn't the one to down-vote this. I actually up-voted it because I thought it was a decent and interesting question. There's a bit of a gray area between *Why* questions and *Opinion-based* questions. Quite often, *Why* questions really are opinion-based and should be closed, but sometimes they do have a legitimate documented answer. I've even been known to ask a [Why Question](http://stackoverflow.com/questions/28415077/why-is-assignment-of-double-to-single-allowed-with-option-strict-on), myself, so I'm not casting stones. – Steven Doggart Mar 27 '15 at 14:17
  • 2
    Since the down-voters never explained their reasons, and no close votes were ever cast, it's hard to say what their reasoning was. If you really want to get the pulse of the community, you could ask about it on meta. – Steven Doggart Mar 27 '15 at 14:18
  • If you know of the event, why are you using the tooling rather than just typing `SomeEvent += ` to create the event handler (you'll be prompted to automatically create a handler method after you type `+= `)? –  Mar 27 '15 at 15:25
  • @Will -- Because I prefer to have all event wire-ups stored in one place, i.e. the designer file `MainForm.Designer.cs`. And it's much easier to use the tooling. If you've ever used VB you'd know what I mean. All you have to do literally is select the event from the drop-down and it creates the handler and wires it up automatically for you. – rory.ap Mar 27 '15 at 15:27
  • 15
    'Why?' is a perfectly legitimate question, to which `[Browsable(false)]` is the answer. There are a lot of knee-jerk reactions around here, especially from the hardened veterans. :) – jnm2 Mar 28 '15 at 14:19
  • 1
    @Trilarion you have changed the original question; Future readers will see that answers are unrelated to the question. Chameleon questions are discouraged. Better add it back. – Sriram Sakthivel Mar 30 '15 at 07:13
  • 2
    Quite frankly, I'm amazed that the down votes are continuing to accrue without a single comment stating why. I'm starting to believe what @ClaraOnager said in my [meta post](http://meta.stackoverflow.com/questions/288816/wondering-why-this-question-was-down-voted-so-many-times-and-how-i-can-improve?noredirect=1#comment170415_288816): "SO is a haven of VB haters and they can express their sentiment anonymously. I'm surprised that any question that even dares to mentions VB in the same context as C# isn't downvoted into oblivion" – rory.ap Mar 30 '15 at 13:00
  • What's wrong with hating VB? :-) – thorn0 Mar 30 '15 at 16:33
  • 2
    @thorn -- Nothing at all (or should I say "`null` at all" -- hee hee), but it's not a reason to down-vote. – rory.ap Mar 30 '15 at 16:34
  • 1
    @roryap To be honest I hate VB but never downvoted any post for that reason. Also getting more upvotes/downvotes is a side effect of asking question in meta referring the stackoverflow post. So, this is quite normal. I've seen posts with +4 votes just came to -5 which means -9 downvotes in just an hour :) Also don't just count the downvotes, you get upvotes too; as of now you got 34 ups. – Sriram Sakthivel Mar 30 '15 at 21:05
  • @Sriram I edited the question in the sense of SO, i.e. to make it more clear. Might be I'm missing something here, but don't you feel the original question is rather badly posed and leaves room for improvement? Maybe someone more proficient can/should do it. – NoDataDumpNoContribution Mar 31 '15 at 18:30
  • @Trilarion Well you could make it better. You are more than welcome to do it. But you have removed the part from question which was the only question OP asked initially. We answered based on that alone, later additions to answers are based on edited question. If you just removed the original question from title, then our answers will be obsolete or may seem irrelevant to future readers. There is a fair chance that people may downvote the answers just because it talks about something else than what being asked(because they don't know question was edited). – Sriram Sakthivel Mar 31 '15 at 18:37
  • @Trilarion -- I'd welcome any feedback you have for making the question better. "the original question is rather badly posed and leaves room for improvement" -- can you elaborate on that? I did expend a great amount of effort and thought on this question in an effort to make it a good one, and thus I'd have to say your cavalier comment is a little off-putting. – rory.ap Mar 31 '15 at 18:39

4 Answers4

27

Well, it is hidden intentionally. If you look at Control class, HandleCreated event is marked with Browsable(false) which means not to show it in properties window.

[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler HandleCreated;

If you ask me why? I don't know the answer. It is a design decision, which any of the person from design team have to answer that.

My guess is that they hide events which are not of more importance. How many times you need to subscribe HandleCreated? You typically subscribe Load event.

Some other good examples of events which falls under same category are ControlAdded, ControlRemoved etc. As you can see these are not very much important, they are hidden from designer.

How to easily subscribe the event in C# editor as like VB.net?

You cannot get the combobox for events as you get for VB.net; Closest what you can get is the ide support which can autocomplete for you (which is already mentioned in @HenkHolterman's answer; now deleted).

type this.HandleCreated += , then tab, tab.

Ide will hook up the events for you.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • 11
    @roryap That's a question which I can't answer. You need to ask msft engineer who was participating in design :) – Sriram Sakthivel Mar 26 '15 at 14:26
  • 2
    Another fun case if the [`TextBoxBase.Paint`](https://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.paint%28v=vs.90%29.aspx) event which is specifically marked as non-browsable, even through the `Control.Paint` method is browsable. This is because `TextBoxBase` class will never actually raise the event, and I'm assuming the designers wanted to remove confusion by preventing people from registering a handler (though it adds some confusion when you're trying to figure out where the Event went). – Anthony Mar 26 '15 at 15:06
  • Quite often I found that events and properties are hidden because they don't actually work as expected in the subclass. TextBox has a few of those especially.. – TaW Mar 26 '15 at 15:08
  • 2
    @Anthony True, that's different actually. Events, properties, methods which are not relevant to the class (they exist just because base class had it) will also be hidden. Worth noting that this is a violation of LSP – Sriram Sakthivel Mar 26 '15 at 15:08
  • @SriramSakthivel: The LSP does not require that derived classes implement all base-class members in *useful* fashion--merely that they implement them in a fashion *consistent with the base-class contract*. An "observable list" interface which allows objects to request notification when something is added or removed could be implemented just fine by an immutable-list type. Often, when code wants an observable list, its interest is in having something *that won't change in ways it doesn't know about*, and an immutable list satisfies that need perfectly. – supercat Mar 26 '15 at 16:12
  • @SriramSakthivel: Because an immutable list won't ever have items added or removed, its event-subscription method need not do anything; further, there's no reason why any code with a reference to something which is *known* to be an immutable list should ever request change notifications. On the other hand, the fact that a list *might* be immutable shouldn't prevent an object which doesn't know whether it is or not from asking "Let me know if you're modified". – supercat Mar 26 '15 at 16:15
  • @supercat My reply was to Anthony's comment which says that `Textbox.Paint` will not raise the paint event when it is painted. Indeed that's a violation of LSP. Contract of `Control.Paint` event is that *hey notify me when you paint yourself* but apparently it is violated by `TextBox`. Do you agree with this? That's what I was talking about, not hiding the events from designer. – Sriram Sakthivel Mar 26 '15 at 17:29
  • @SriramSakthivel: Whether it's an LSP violation depends upon whether one views the contract as firing `Paint` whenever an object paints itself, or whenever the object needs to have part of its GDI drawing surface rendered. From what I understand, textbox content is not rendered as part of a control's GDI drawing surface but is instead shown in a separate object which is drawn "above" the GDI drawing surface and totally obscures it. The behavior would be somewhat analogous to a media player which on some platforms (at least historically) would be handled by... – supercat Mar 26 '15 at 17:56
  • ...drawing with a key-color all parts of the 'main' bitmap that should show media content, and then having the media content itself rendered to a separate buffer. Even if the media player was showing a 30fps video it wouldn't generate paint events for its window, since the code for drawing the underlying window would play no part in the rendering of the content. Textbox rendering isn't quite that far isolated from the rendering of textbox controls, but it isn't all that far from it. – supercat Mar 26 '15 at 17:59
  • @supercat As a consumer of an abstraction, I don't want know about how textbox renders itself, how complex it is etc. As per mdsn `Control.Paint` says that *Occurs when the control is redrawn* but `Textbox` doesn't raises the paint event when it redraws. And that's clearly a violation of LSP. You could argue that I'm looking at a contract in different perspective; but that's what msdn says. You should admit it. – Sriram Sakthivel Mar 26 '15 at 18:02
  • @SriramSakthivel: There are many places where classes were poorly documented in 1.0 and the documentation has never been improved. If `TextBox` were documented as being what it actually is--a request to have a Windows textbox control overlaid on top of a certain part of the form--the fact that parts of the screen are "owned" by Windows rather than the application would justify the behavior from an LSP standpoint. I view the deficiencies in the documentation as being broader than an LSP violation, and fixing the deficiencies could correct any apparent LSP violations. – supercat Mar 26 '15 at 18:12
  • @SriramSakthivel -- If you can touch upon whether and how it's possible to "quickly" create event handlers in C# like in VB.NET (to be clear, I know the answer is probably that it's not possible), then I will accept this answer. – rory.ap Mar 28 '15 at 01:09
16

The VB.NET and the C# IDEs only look superficially the same. They worked from a pretty decent look-and-feel specification. But that's where the resemblance stops, they were created by two very different groups at Microsoft and have drastically different code-bases. Otherwise a survival strategy for large software companies, big groups don't work.

Most importantly, they had dramatically different goals. The C# team had the luxury of starting completely from scratch, always nice when you don't have anybody to keep happy and have no baggage to lug around. Not so for the VB.NET team, Visual Basic has been a popular product for a very long time with strong IDE support that goes back 25 years. Most important for them was to give their customers a familiar experience back, VB.NET was already a major upheaval that was very controversial.

The way those two combo-boxes at the top of the edit window work was cast in granite bedrock stone. They never filtered anything before. If the VB.NET programmer wrote an event handler for an event then he expects to always find it back in the combobox. It works the other way around as well, the VB.NET IDE hides a lot of information. Like not showing the auto-generated source files in the Solution Explorer window.

Don't make too many assumptions about how it should work, you're likely to guess wrong. And have few options to do something about it.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

Imagine you have a user-control which has both UI and non-UI properties. You need to decorate non-UI properties with Browsable(False) so that they will not be available through the properties window.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohit
  • 10,056
  • 7
  • 50
  • 82
0

To answer your second question, you can't quickly create event handlers as you would in VB.NET. This is one of the differences of VB.NET to C# beyond syntax.

In VB.NET, you can decorate a field with the WithEvents modifier, which is a requirement for creating "quick event handlers". This translates to a new property that will do all the event registration stuff for you. This WithEvents is implicitly created for the this (or Me) pointer as well. C# does not have this syntax feature and thus, it is not possible, so you have to do that manually. After all, the difference between VB.NET and C# has never been only syntax, just almost only syntax :)

I guess the reason is that C# was designed to restrict the amount of keywords to a bare minimum, whereas Microsoft never hestitated to add more keywords to VB.NET. If you consider the LINQ syntax elements, there are a couple of more keywords newly introduced into VB.NET than into C#.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Georg
  • 5,626
  • 1
  • 23
  • 44
  • The significance of `WithEvents` goes beyond the convenience of writing code; it also greatly simplifies attachment of events within the UI designer, and helps eliminate event leaks. Interestingly, even before the advent of auto-property syntax, `WithEvents` could be used to make something an auto-property even if it didn't actually have any events. – supercat Mar 26 '15 at 16:19
  • @supercat I would disagree. Although it does greatly simplify the attachments of events with the UI designer and helps eliminate event leaks, I would still regard this as a convenience. You can do the very same thing in C# manually and it is actually a pretty good idea to do so. But I guess this is rather an academic discussion whether or not something is "only" convenience. – Georg Mar 26 '15 at 17:18
  • 1
    Using `WithEvents` allows the same lines of source code to handle event subscription and unsubscription. In C#, the closest one could come to DRY would be to write properties similar to the ones VB auto-generates; the setter would need a list of event-unsubscribe statements and event-subscribe statements, but at least they'd be close together. Adding a handler in VB.NET only requires a single `Handles xx.EventName` declaration on the method header, which then automatically adds both the unsubscription and subscription actions to the auto-generated property. – supercat Mar 26 '15 at 17:47
  • Yes, if your definition of beyond convenience is that it helps you to reduce breaches to the DRY, you are absolutely right and this is probably also a very good definition of "beyond convenience". On the other hand, this is also true for most syntactic sugars. But maybe the borderline between syntactic sugar and "beyond convenience" syntax elements is that the latter help you to reduce specify in one place what would otherwise be split among the code. Also in that case, you are right :) – Georg Mar 27 '15 at 07:53
  • IMHO, one of the major goals of a good language should be to minimize DRY breaches. For the common situation where a field (or an event-subscribing "field") will hold the same thing throughout the lifetime of an object, code should only need to devote one line to the field, and one annotation for each event handler. Unfortunately, at present there's no clean way for point-of-declaration initialization clauses to get access to constructor parameters nor specify a cleanup action, which means that many fields end up needing a line of declaration, a line in the constructor to set them up, and... – supercat Mar 27 '15 at 15:10
  • ...then need additional code to clean them up. I'd like to see a language include a good way to specify everything for the common use cases at the point of declaration, rather than requiring field declarations, initialization, and cleanup to be located at three separate places in the code. – supercat Mar 27 '15 at 15:15