Pytanie Co sprawia, że ​​nie każde wydarzenie jest dostępne w projektancie i jak mogę szybko wygenerować procedury obsługi w języku C #, jak w VB.NET?


W projektancie formularzy programu Visual Studio można dodać procedurę obsługi zdarzeń w oknie Właściwości na liście "Zdarzenia", klikając go dwukrotnie. Możesz także dodać obsługę zdarzeń - przynajmniej w VB.NET - w widoku kodu, wybierając skojarzony element "Wydarzenia" z menu po lewej stronie, a następnie żądane wydarzenie w menu po prawej stronie. Moje pytanie brzmi: jak to się dzieje, że niektóre wydarzenia są dostępne tylko za pomocą tej drugiej techniki, a nie w pierwszej? Na przykład HandleCreated zdarzenie jest dostępne w widoku kodu:

enter image description here

Ale nie w projektancie:

enter image description here

W VB.NET jest to w porządku, ponieważ zawsze mogę użyć pierwszej techniki, aby szybko wygenerować programy obsługi zdarzeń. Jednak w języku C # pierwsza technika nie jest możliwa, ale problem nadal istnieje; Oznacza to, że niektóre zdarzenia nie pojawiają się na liście projektantów w oknie Właściwości. Jedynym innym sposobem, w jaki wiem o tworzeniu programu obsługi zdarzeń, jest ręczne dodanie go, co obejmuje ręczne podłączenie obsługi zdarzenia.

Czy jest coś technicznego, co sprawia, że ​​niektórych zdarzeń brakuje na projektowanej liście wydarzeń w oknie Właściwości? Biorąc pod uwagę, że to prawda, w jaki sposób można szybko generować programy obsługi zdarzeń w języku C #, tak jak ja w VB.NET?


26
2018-03-26 14:20


pochodzenie


Nie głosowałem, ale podejrzewam, że powodem jest to, że pytasz "dlaczego", a nie "jak". "Jak" to dobre pytanie. "Dlaczego" jest bardziej subiektywne i oparte na opiniach (brakuje jakiejś oficjalnej dokumentacji rozumowania). - Steven Doggart
Ponieważ ci, którzy głosują w dół, nigdy nie wyjaśnili swoich racji i nie oddano nigdy żadnych głosów, trudno powiedzieć, jakie były ich argumenty. Jeśli naprawdę chcesz uzyskać puls społeczności, możesz zapytać o to na meta. - Steven Doggart
'Czemu?' jest całkowicie uzasadnionym pytaniem, do którego [Browsable(false)] jest odpowiedzią. Jest tu wiele odruchowych reakcji, szczególnie ze strony zatwardziałych weteranów. :) - jnm2
Szczerze mówiąc, jestem zdumiony, że głosy w dół wciąż rosną, bez jednego komentarza stwierdzającego, dlaczego. Zaczynam wierzyć w to, co powiedział mi @ClaraOnager meta post: "SO jest przystanią dla nienawidzących VB i mogą oni anonimowo wyrażać swoje uczucia Jestem zaskoczony, że każde pytanie, które ośmiela się wspomnieć VB w tym samym kontekście co C #, nie jest odrzucane w zapomnienie" - rory.ap
@thorn - Nic w ogóle (lub powinienem powiedzieć "null w ogóle "- hee hee), ale nie jest to powód do głosowania w dół. - rory.ap


Odpowiedzi:


Cóż, jest to ukryte celowo. Jeśli spojrzysz na klasę Control, HandleCreated wydarzenie jest oznaczone symbolem Browsable(false) co oznacza, że ​​nie ma tego pokazywać w oknie właściwości.

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

Jeśli pytasz mnie, dlaczego? Nie znam odpowiedzi. Jest to decyzja projektowa, na którą każda osoba z zespołu projektowego musi odpowiedzieć.

Domyślam się, że ukrywają wydarzenia, które nie mają większego znaczenia. Ile razy trzeba subskrybować HandleCreated? Zazwyczaj subskrybujesz Load zdarzenie.

Inne dobre przykłady wydarzeń należących do tej samej kategorii ControlAdded, ControlRemoved itp. Jak widać, nie są one bardzo ważne, są ukryte przed projektantem.

Jak łatwo zapisać wydarzenie w edytorze C # jak w VB.net?

Nie można uzyskać combobox wydarzeń, jak można uzyskać na VB.net; Najbliżej można uzyskać wsparcie dla idei, które może być autouzupełnianie dla ciebie (które jest już wspomniane w odpowiedzi @ HenkHolterman, teraz usunięte).

rodzaj this.HandleCreated += , następnie patka, patka.

Ide podłączy wydarzenia dla ciebie.


27
2018-03-26 14:24



Więc dlaczego? - rory.ap
@Roryap To jest pytanie, na które nie mogę odpowiedzieć. Musisz zapytać inżyniera msft, który brał udział w projektowaniu :) - Sriram Sakthivel
Kolejny ciekawy przypadek, jeśli TextBoxBase.Paint Zdarzenie, które jest specjalnie oznaczone jako niemożliwe do przeglądania, nawet przez Control.Paint Metoda jest dostępna do przeglądania. To dlatego, że TextBoxBase Klasa nigdy nie podniesie zdarzenia i zakładam, że projektanci chcieli usunąć zamieszanie, uniemożliwiając rejestrację handler'a (chociaż wprowadza to zamieszanie, gdy próbujesz dowiedzieć się, gdzie wydarzenie się wydarzyło). - Anthony
Dość często odkryłem, że zdarzenia i właściwości są ukryte, ponieważ nie działają zgodnie z oczekiwaniami w podklasie. TextBox ma kilka z nich szczególnie .. - TaW
@Anthony Prawda, w rzeczywistości jest inaczej. Zdarzenia, właściwości, metody, które nie mają związku z klasą (istnieją tylko dlatego, że klasa podstawowa je posiada) również będą ukryte. Warto zauważyć, że jest to naruszenie LSP - Sriram Sakthivel


VB.NET i C # IDE wyglądają tylko powierzchownie. Pracowali z całkiem przyzwoitą specyfikacją wyglądu i odczuwania. Ale w tym miejscu podobieństwo się zatrzymuje, zostały stworzone przez dwie bardzo różne grupy w Microsoft i mają drastycznie odmienne podstawy kodu. W przeciwnym razie strategia przetrwania dużych firm z branży oprogramowania, duże grupy nie działają.

Co najważniejsze, mieli zupełnie inne cele. Zespół C # miał luksus zaczynać od zera, zawsze miło, gdy nie ma nikogo, kto by był szczęśliwy i nie miał bagażu do noszenia. Inaczej niż w przypadku zespołu VB.NET, Visual Basic jest popularnym produktem od bardzo dawna, z silną obsługą IDE, która trwa już 25 lat. Najważniejsze dla nich było zapewnienie swoim klientom znanego doświadczenia, VB.NET był już poważnym wstrząsem, który był bardzo kontrowersyjny.

Sposób, w jaki te dwa pola kombi w górnej części okna edycji były odlane z granitowego kamienia skalnego. Nigdy wcześniej nie filtrowali niczego. Jeśli programista VB.NET napisał obsługę zdarzeń dla zdarzenia, spodziewa się, że zawsze znajdzie ją z powrotem w comboboxie. Działa to również w drugą stronę, VB.NET IDE ukrywa wiele informacji. Podobnie jak nie pokazuje automatycznie generowanych plików źródłowych w oknie Solution Explorer.

Nie rób zbyt wielu założeń na temat tego powinien pracuj, prawdopodobnie zgadniesz źle. I mam kilka opcji, aby coś z tym zrobić.


16
2018-03-26 14:30





Wyobraź sobie, że masz kontrolę użytkownika, która ma zarówno właściwości interfejsu użytkownika, jak i nie-interfejsu użytkownika. Musisz udekorować właściwości inne niż interfejs użytkownika Browsable(False) aby nie były dostępne w oknie właściwości.


1
2018-03-26 14:43





Aby odpowiedzieć na drugie pytanie, nie można szybko utworzyć procedur obsługi zdarzeń, tak jak w VB.NET. Jest to jedna z różnic w składni języka VB.NET do C #.

W VB.NET możesz udekorować pole za pomocą WithEvents modyfikator, który jest wymagany do tworzenia "szybkich procedur obsługi zdarzeń". Przekłada się to na nową właściwość, która zrobi dla Ciebie wszystkie rzeczy związane z rejestracją zdarzeń. To WithEvents jest również domyślnie utworzony dla tego wskaźnika (lub Ja). C # nie ma tej funkcji składni i dlatego nie jest możliwe, więc musisz to zrobić ręcznie. W końcu różnica między VB.NET i C # nigdy nie była tylko składnią, tylko prawie składnią :)

Chyba dlatego, że C # został zaprojektowany, aby ograniczyć liczbę słów kluczowych do absolutnego minimum, podczas gdy Microsoft nigdy nie starał się dodać więcej słów kluczowych do VB.NET. Jeśli uważasz, że LINQ elementy składni, jest kilka więcej słów kluczowych nowo wprowadzonych do VB.NET niż do C #.


0



Znaczenie WithEvents wykracza poza wygodę pisania kodu; to także znacznie upraszcza dołączanie zdarzeń do projektanta interfejsu użytkownika i pomaga wyeliminować wycieki zdarzeń. Co ciekawe, nawet przed nadejściem składni auto-właściwości, WithEvents może być użyty do uczynienia czegoś auto-własnością, nawet jeśli nie ma żadnych zdarzeń. - supercat
@supercat Nie zgodziłbym się. Chociaż znacznie upraszcza załączniki zdarzeń z projektantem interfejsu użytkownika i pomaga wyeliminować wycieki zdarzeń, nadal uważałbym to za wygodę. Możesz zrobić to samo w C # ręcznie i jest to całkiem niezły pomysł, aby to zrobić. Ale myślę, że to raczej akademicka dyskusja, czy coś jest "tylko" wygodą. - Georg
Za pomocą WithEvents umożliwia takie same linie kodu źródłowego, aby obsłużyć subskrypcję zdarzeń i wypisać subskrypcję. W języku C # najbliżej przychodzącym do DRY byłoby zapisywanie właściwości podobnych do tych generowanych automatycznie przez VB; seter będzie potrzebował listy wyciągów zdarzeń i wypisów subskrypcji, ale przynajmniej będą blisko siebie. Dodawanie programu obsługi w VB.NET wymaga tylko jednego Handles xx.EventName deklaracja nagłówka metody, która następnie automatycznie dodaje zarówno akcje rezygnacji, jak i subskrypcji do automatycznie wygenerowanej właściwości. - supercat
Tak, jeśli twoją definicją nieporównywalną jest to, że pomaga ci to ograniczyć naruszenia DRY, masz absolutną rację i jest to prawdopodobnie bardzo dobra definicja "poza wygodą". Z drugiej strony jest tak również w przypadku większości cukrów składniowych. Być może jednak granica między cukrem syntaktycznym i elementami składowymi "poza wygodą" polega na tym, że te ostatnie pomagają w określeniu w jednym miejscu, co w innym przypadku byłoby rozdzielone pomiędzy kod. Również w tym przypadku masz rację :) - Georg
IMHO, jednym z głównych celów dobrego języka powinno być minimalizowanie przypadków naruszenia DRY. Dla typowej sytuacji, w której pole (lub "pole" subskrybujące zdarzenia) będzie utrzymywać to samo przez cały okres istnienia obiektu, kod powinien tylko poświęcić jedną linię na pole i jedną adnotację dla każdej procedury obsługi zdarzenia. Niestety, obecnie nie ma czystej drogi dla klauzul inicjalizujących punkt deklaracji, aby uzyskać dostęp do parametrów konstruktora, ani nie określają akcji czyszczenia, co oznacza, że ​​wiele pól kończy się wymagając linii deklaracji, linii w konstruktorze, aby je ustawić. , i... - supercat