Dodawanie metod do zdarzeń klas wewnątrz innych klas.

0

Może trochę niejasny temat ale jak najbardziej oddaje to o co chce spytać.
Mianowicie jeżeli mam własną klasę taką jak przykładowo ta:

public class Menu
{
        private Button B {get;set;}
//....
        public Menu(string T)
         {
            B.Content = T;
          }
//....

To czy istnieje jakiś sposób aby stworzyć jakąś metode wewnątrz klasy która by była w stanie przypisać do zdarzenia B.Click metodę spoza tej klasy?

0

Da się, wystarczy żeby metoda przyjęła odpowiedni delegat, a potem zarejestrowała go w zdarzeniu przycisku. Ale to zły pomysł, bo uzależniasz zewnętrzne klasy od wewnętrznej implementacji.
Powinieneś w swojej klasie zrobić publiczne zdarzenie, które byłoby wyzwalane po kliknięciu w przycisk, i które będziesz subskrybował w innych klasach.

0

Może wyjaśnie szczegołowo o co mi chodzi.... Mam metode serializującą która będzie serializować List<Kategoria> przypuśćmy. Klasa kategoria w zasadzie składa się ze stringów i booli i jest to klasa która ma być serializowana po wciśnięciu przycisku B w klasie Menu. Zapomniałem wczoraj dodać do konstruktora klasy( późno już było) dynamiczne tworzenie kontrolki Button. Ale teraz widze, że jak mam Button private to chyba będzie lepiej zrobić tak jak mówisz. Tylko nie mam pojęcia jak do takiego zdarzenia przesłać List<Kategoria> skoro zdarzenia zwykle przyjmują dwa parametry:

public static void Zdarzenie(object sender,EventArgs e)
0

Jeśli zdefiniujesz swoje zdarzenie, to możesz mu przekazać swoją klasę dziedziczącą z EventArgs i zawierającą takie dane, jakie chcesz.

Ale z tego, co napisałeś, wynika raczej, że Twoim problemem jest brak projektu aplikacji, którą robisz i niezastosowanie żadnych warstw. Na Twoim miejscu spróbowałbym zastosować architekturą opartą o wzorzec MVP.

0

Ja dodam, że sender i EventArgs to tylko konwencja. Własny event może mieć dowolne parametry, albo nawet brak parametrów.

0
using System;

// klasa ze zdarzeniem
class Kasza
{
	// to jest nasze zdarzenie
	public event EventHandler OnMyEvent;

	// to jest jakaś inna metoda, w której wywoływane jest zdarzenie
	public void WywołajZdarzenie()
	{
		if (OnMyEvent != null)
			OnMyEvent(this, null); // przekazujemy sender i e
	}
}

// klasa z procedurą obsługi zdarzenia
class Test
{
	// to jest nasz event handler, który podpiszemy pod zdarzenie
	static void kasza_event(object sender, EventArgs e)
	{
		// `sender` to obiekt (typu Kasza), który wywołał zdarzenie
		// `e` jest w naszym przypadku zawsze nullem
		Console.WriteLine("event!");
	}

	static void Main()
	{
		Kasza kasza = new Kasza();

		// subskrypcja zdarzenia
		kasza.OnMyEvent += kasza_event;

		// poniższa linijka wywoła eventa
		kasza.WywołajZdarzenie();
	}
}
0

Może ubiorę to trochę bardziej w treść.
Na początek dodam, że aplikacja jest pisana na kafelkowy windows8, ale to nie powinno mieć jakiegoś większego znaczenia.
Moja klasa do której elementu zdarzenia chciałbym się dostaę wygląda tak...

class Kategoria 
    {
        private CheckBox Kw { get; set; }
        private TextBox Kat { get; set; }
        private StackPanel Frame { get; set; }
        private Button Add { get; set; }
        private TextBox Kwota { get; set; }
       
        public Kategoria()
        {
            Kw = new CheckBox();
            Kat = new TextBox();
            Frame = new StackPanel();
            Add = new Button();
            Kwota = new TextBox();

            Kw.Content = "Stała kwota?";
            Kat.Text = "Nazwa kategorii";
            Add.Content = "Dodaj";
            Kwota.Text = "Miesięczna kwota";

            Kw.Checked+=Kw_Checked;
            Kw.Unchecked+=Kw_Unchecked;
            //Add.Click +=--------------????--------------------- ;
            Frame.Orientation = Orientation.Horizontal;
            Frame.Children.Add(Kw);
            Frame.Children.Add(Kat);
            Frame.Children.Add(Add);
            
        }
        
       
        private void Kw_Unchecked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            Frame.Children.Remove(Kwota);
        }

        private void Kw_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            Frame.Children.Remove(Add);
            Frame.Children.Add(Kwota);
            Frame.Children.Add(Add);
        }
        
        public StackPanel GetHndlr()
        {
            return Frame;
        }

    } 

Klasa która ma być serializowana:

 public class Option
    {
        public bool Checked { get; set; }
        public string Title { get; set; }
        public string Value { get; set; }

        public Option(bool check, string title, string value)
        {
            Checked = check;
            Title = title;
            Value = value;
        }
    }

A tutaj moja metoda serializująca ( nie jest jeszcze kompletna, ale to brak dosłownie dwóch linijek gdzie będzie dodawany nowy obiekt typu Opt do listy );

 private async Task Serialize(List<Option> Op)
        {
            
            using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync("Opcje.txt", CreationCollisionOption.ReplaceExisting))
            {
                XmlSerializer Serializer = new XmlSerializer(typeof(List<Option>));
                using (XmlWriter xml = XmlWriter.Create(stream, new XmlWriterSettings() { Indent = true }))
                {
                   Serializer.Serialize(xml, Op);
                }
            }

        }

Chodzi mi głownie o to żeby po kliknięciu na przycisk dodaj z klasy Kategoria wywołana została metoda Serialize.

0

Add.Click += (s,e) => opcje.Serialize()? Ewentualnie dodaj zdarzenia w kategorii typu OnAdd, ... i niech Add.Click deleguje do tego eventa.

0

Szczerze powiedziawszy to nie za bardzo mam pojęcie jak to zrealizować.

zrobiłem coś takiego ale jak wiadomo nie można tego za bardzo przekonwertować.

public void Dodaj_Clicked(Task T)
        {
            this.Add.Click +=(Windows.UI.Xaml.RoutedEventHandler) T;
        } 

Musi być Task bo taki jest typ zwracany przez asynchroniczna klase serializuj.
Poza tym do delegata RoutedEventHandler jki przyjmuje zdarzenie Add.Click pasuje tylko przeciazenie typu void (s,e) wiec nie mam pojęcia jak mogę przesłać motede która nie posiada tych dwoch parametrów i zwraca zupełnie inny typ.

EDIT:

Jakoś sobie poradziłem:

 Kategoria Cat = new Kategoria(new RoutedEventHandler(Dodaj_clicked));

Dodałem do konstruktora klasy przeciążenie dla którego kontruktor ten przyjmuje parametr typu RoutedEventHandler( który można z powodzeniem podpiąć pod zdarzenie Click).
Zwykła metoda typu Dodaj_clicked(s,e) wywołuje następnie porządana przeze mnie metode serialize. Trochę taka reakcja łańcuchowa i wiem, że można to całkiem inaczej zrobić ale czasem trzeba i tak :D. przekazywana metoda w tym wypadku musi tak wyglądać raczej bo taką konstrukcje ma też delegat zdarzenia Click. Problem uważam za rozwiązany niemniej jestem ciekaw czy można jakoś pomimo takiego delegata tego zdarzenia podpiąć do niego metode która przyjmowałaby inne parametry?

1 użytkowników online, w tym zalogowanych: 0, gości: 1