2008-09-18 18 views
12

W pewnym sensie cofnąłem się w kąt.Dziedziczenie obsługi zdarzeń w C#

Mam serię kontrolek UserControl, które dziedziczą po rodzicu, który zawiera kilka metod i zdarzeń w celu uproszczenia rzeczy, więc nie muszę pisać linii i linii prawie identycznego kodu. Tak jak ty. Jednostka nadrzędna nie zawiera żadnych innych elementów sterujących.

To, co chcę zrobić, to mieć jedną procedurę obsługi zdarzeń w nadrzędnej kontrolce UserControl, która wykonuje i wykonuje operacje, które może wykonać tylko kontrola nadrzędna (to jest warunkowe wywoływanie zdarzenia, tak jak zdarzenie zdefiniowano w obiekcie nadrzędnym) . Następnie podłączyłem tę procedurę obsługi zdarzeń do wszystkich moich pól wejściowych w kontrolkach podrzędnych, a elementy sterujące podrzędne posortowałyby zadanie analizowania danych wejściowych i powiadamiając nadrzędną kontrolę, czy należy rzucić to zdarzenie. Miły i czysty, bez powtarzających się, kopiuj-wklej kod (który dla mnie zawsze powoduje błąd).

Oto moje pytanie. Visual Studio uważa, że ​​jestem zbyt sprytny o połowę i ostrzega mnie, że "metoda" CheckReadiness "[procedura obsługi zdarzeń w rodzica] nie może być metodą dla zdarzenia, ponieważ klasa, z której pochodzi ta klasa, już definiuje tę metodę." Tak, Visual Studio, to punkt. I chcę, aby miał obsługę zdarzeń, która obsługuje tylko zdarzenia generowane przez klasy potomne, a jej jedynym zadaniem jest umożliwienie mi podpięcia dzieci bez konieczności pisania pojedynczego wiersza kodu. Nie potrzebuję tych dodatkowych modułów obsługi - wszystkie potrzebne funkcje są oczywiście wywoływane, gdy dzieci przetwarzają dane wejściowe użytkownika.

Nie jestem pewien, dlaczego Visual Studio zaczęło narzekać na to teraz (ponieważ pozwoliło mi to wcześniej) i nie jestem pewien, jak to zrobić, aby odszedł. Najlepiej, chciałbym to zrobić bez konieczności definiowania metody, która po prostu wywołuje CheckBeadiness. Co powoduje to ostrzeżenie, co powoduje pojawienie się teraz, gdy nie minęło godzinę temu, i jak mogę to zrobić, nie uciekając się do robienia małych opiekunów we wszystkich zajęciach dla dzieci?

Odpowiedz

7

stwierdzenie sposób macierzystych wirtualnych, zastąpi go w klasach dzieci i wywołać

base.checkReadyness(sender, e); 

(lub jego derevation) od wewnątrz klasy dzieci. Pozwala to na przyszłą ewolucję projektu, jeśli chcesz wykonać jakiś konkretny kod sprawdzania błędów przed wywołaniem obsługi zdarzenia nadrzędnego. Być może nie będziesz musiał pisać milionów programów obsługi zdarzeń podobnych do tego dla każdej kontrolki, możesz po prostu napisać jedną, podpiąć wszystkie kontrolki do tego programu obsługi zdarzeń, który z kolei wywoła funkcję obsługi zdarzeń rodzica.

Jedną rzeczą, którą zauważyłem jest to, że jeśli cały ten kod zostanie umieszczony w bibliotece DLL, może wystąpić uderzenie wydajności próbujące wywołać procedurę obsługi zdarzenia z biblioteki DLL.

+0

To by rozwiązało problem, ale miałem nadzieję uniknąć zasadniczo pustych procedur obsługi błędów, stąd moje pytanie. – Merus

+0

Nie sądzę, że są one zbędne, ale kontrolery i programy obsługi zdarzeń są zasadniczo umieszczone w tym samym miejscu.Może to (w zależności od układu kodu) prowadzić do lepszej czytelności kodu itp. Jest to po prostu, że cała praca odbywa się gdzie indziej! –

+0

Wydaje się, że należy postępować ... wydaje się, że to tylko problem projektanta ... –

0

Jeśli wydarzenie jest już zdefiniowane w klasie nadrzędnej, nie trzeba go ponownie pisać w klasie dziecka. To spowoduje dwukrotne wystrzelenie zdarzenia.

Sprawdź, czy tak się dzieje. HTH :)

0

Ten artykuł na temat MSDN powinien być dobrym punktem wyjścia: Overriding Event Handlers with Visual Basic .NET. Spójrz na W jaki sposób klauzula uchwytów może powodować problemy w sekcji pochodnej klasy.

+0

To jest artykuł Visual Basic. Problem, który omawiają, nie będzie problemem w języku C#. To może wyjaśnić, dlaczego barki VS na coś, co powinno być uzasadnione, choć. –

0

Dlaczego nie deklarować metody jako wirtualnej w klasie nadrzędnej, a następnie można ją zastąpić w klasach pochodnych w celu dodania dodatkowej funkcjonalności?

+0

Więc nie muszę pisać instrukcji obsługi dla każdej klasy, które są identyczne. To są dość małe kontrole. Nie potrzebuję zbyt dużo dodatkowej funkcjonalności. – Merus

0

Zapomnij o tym, że jest to program obsługi zdarzeń i po prostu wykonaj normalne nadpisanie metody w klasie potomnej.

3

Właśnie spotkałem się z tym, zgadzam się, że wydaje się, że robisz wszystko poprawnie. Deklaracja, że ​​metoda wirtualna jest najlepszym rozwiązaniem, a nie rozwiązaniem.

To, co się robi, jest poprawne - kontrola, która istnieje tylko w klasie pochodnej, a klasa pochodna dołącza procedurę obsługi zdarzeń do jednego ze zdarzeń tej kontrolki. Fakt, że metoda obsługi zdarzenia jest zdefiniowana w klasie bazowej, nie jest ani tutaj, ani tam, jest dostępny w miejscu powiązania z wydarzeniem. Zdarzenie nie jest dołączane do dwukrotności lub coś takiego głupiego, jest to po prostu kwestia, gdzie zdefiniowana jest metoda, która obsługuje zdarzenie.

Zdecydowanie nie jest to metoda wirtualna - nie chcę, aby metoda była możliwa do zastąpienia przez klasę pochodną. Bardzo frustrujące i moim zdaniem błąd w dev-studio.

1

Po prostu napotkano problem Merus, który powstał jako pierwszy i, podobnie jak inni, którzy pisali odpowiedzi, nie jestem do końca jasny, dlaczego VS (używam teraz obiektów Visual C# 2010 Express) do obsługi zdarzenia zdefiniowane w klasie bazowej. Powodem, dla którego publikuję odpowiedź, jest to, że w procesie rozwiązywania problemu poprzez uczynienie kodu klasy podstawowej metodą chronioną, którą klasy pochodne wywołują po prostu w swoich (zasadniczo pustych) programach obsługi zdarzeń, zmieniłem nazwę bazy Metoda klasy i zauważyłem, że projektant VS przestał narzekać. To znaczy, zmieniła nazwę na rejestrację programu obsługi zdarzeń (tak, że nie przestrzegała już konwencji projektanta VS nazwanych programów obsługi zdarzeń o nazwie ControlName_EventName) i to zdawało się ją satysfakcjonować. Kiedy następnie próbowałem zarejestrować (obecnie zmienioną nazwę) podstawowy program obsługi zdarzeń względem pochodnych kontrolek klas, wprowadzając nazwę w odpowiednim zdarzeniu VS, projektant utworzył nową procedurę obsługi zdarzeń w klasie pochodnej, którą następnie usunąłem, pozostawiając zarejestrowaną klasę klasy zarejestrowaną do metody klasy bazowej (obsługi zdarzeń). Net, jak można się spodziewać, C# znajdzie to, co chcemy zrobić legalnie. Tylko projektant VS nie lubi tego, gdy postępujesz zgodnie z konwencją nazewnictwa zdarzeń projektanta. Nie widzę potrzeby, aby projektant pracował w ten sposób. Anywho, czas na kontynuację.

0

Oto co zrobiłem, aby uzyskać bazowych metod zwanych w kilku podobnych postaciach, patrząc, każdy z nich posiada kilka dodatkowych funkcji, które spotykane:

 protected override void OnLoad(EventArgs e) 
    { 
     try 
     { 
      this.SuspendLayout(); 
      base.OnLoad(e); 

      foreach (Control ctrl in Controls) 
      { 
       Button btn = ctrl as Button; 
       if (btn == null) continue; 

       if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnAdd_Click); 
       else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnEdit_Click); 
       else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnDelete_Click); 
       else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnPrint_Click); 
       else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnExport_Click); 
      } 

Szansa na zaniechaniu stosowania prawa stały nazwa przycisku wygląda tak samo jak szansa nie ręcznego ręcznego poprowadzenia odziedziczonego programu obsługi.

Należy zauważyć, że może zajść potrzeba przetestowania tej metody.DesignMode, aby w ogóle pominąć kod w programie VS Designer, ale działa on dobrze nawet bez sprawdzania.

2

Też doświadczyłem tego problemu, ponieważ we wcześniejszych wersjach VS można było "dziedziczyć" procedury obsługi zdarzeń. Tak więc rozwiązanie, które znalazłem bez konieczności nadpisywania metod, polega po prostu na przypisaniu obsługi zdarzeń gdzieś w fazie inicjalizacji formularza. W moim przypadku, odbywa się w konstruktorze (jestem pewien OnLoad() będzie działać jak dobrze):

public MyForm() 
    { 
     InitializeComponent(); 
     btnOK.Click += Ok_Click; 
    } 

... gdzie treser Ok_Click rezyduje w formie podstawowej. Jedzenie dla myśli.