Myślisz, że zarabiasz tyle, na ile zasługujesz? Zapraszamy do wzięcia udziału w anonimowej ankiecie.
3

1

Witam wszystkich.
Walczę z pewnym problemem dotyczącym GUI, statusLabel i ProgressBarem. Mianowicie czy istnieje możliwość informowania użytkownika o postępie prac nad tworzonym obiektem?
Może przykład ciut więcej wyjaśni:
mamy okienko z przycikiem "start" i statusLabel oraz progressBar w ToolStrip na dole okienka. Przycisk "start" tworzy nowy obiekt np: samochod - czyli jest wywolywany konstruktor klasy samochod. Teraz jezeli w konstruktorze klasy samochod znajdują się wywołania konstruktorów innych klas (np. szyba, kolo, kierownica, fotel, kanapa, itd) to za jednym zamachem tworzy nam się gotowy obiekt typu samochod (co jest logiczne i proste - nie musimy się martwić o tworzenie tego samodzielnie - wszystko zrobi jeden konstruktor).
Wiadomo, że do informowania tego typu najlepiej sprawdzą się delegaty i zdarzenia, ale nie można zasubskrybować delegata danej klasy jeśli obiekt danej klasy nie istnieje, prawda?
Chodzi o to, że można zrobić swoją klasę zdarzenia, której obiekt będzie zawsze wywoływany, gdy coś się zdarzy: zrobiono szybę, zrobiono koło, zrobiono fotel, a okienko ze statusLabel i progresBarem będzie miało metody przyjmujące takie zdarzenia...

Przykład:

{...//klasa Form1
public void updateToolInfo(samochodoweZdarzenie e)
    {
        this.statusLabel = e.msg;
        if (e.value != -1) this.progressBar.Value = e.value;
        if (e.max != -1) this.progressBar.Maximum = e.max;
        if (e.min != -1) this.progressBar.Minimum = e.min;
    }
   ...
   samochod _syrenka;
    private void przyciskStworzSamochod_Click(object sender, EventArgs e)
    {
//sybskrybcja zdarzen tworzonych przez klase samochod jest niemozliwa, 
//bo _syrenka wskazuje na null
_syrenka.delegatAutomobilowy += new samochodowyDelegat(updateToolInfo);//BLAD!!
        _syrenka = new samochod();

 //natomiast zasubskrybowanie w tym miejscu jest jak najbardziej w porzadku, 
 //tyle ze juz za pozno..., bo wszystkie zdarzenia 
 //generowane sa z konstruktora samochod()
        _syrenka.delegatAutomobilowy += new samochodowyDelegat(updateToolInfo);
    }
    ...
    ...}//koniec klasy Form1

public delegate void samochodowyDelegat(samochodoweZdarzenie e);

public class samochodoweZdarzenie : EventArgs
{
    public samochodoweZdarzenie(string message, int value, int max, int min)
    {
        this.msg = message;
        this.value = value;
        this.max = max;
        this.min = min;
    }
    public readonly int value;
    public readonly int max;
    public readonly string msg;
    public readonly int min;
}

//a tu przykladowy kod klasy samochod
class samochod
{

    //egzemplarz delegata
    public samochodowyDelegat delegatAutomobilowy;


    Kierownica _kier;
    internal Kierownica kier
    {
        get { return _kier; }
        set { _kier = value; }
    }

    List<Kolo> _lstKola = new List<Kolo>();
    internal List<Kolo> LstKola
    {
        get { return _lstKola; }
        set { _lstKola = value; }
    }


    public samochod()
    {

        _Kier = new Kierownica();
        //
        //jak w tm miejscu poinformowac, ze kierownica zostala zrobiona???
        //skoro obiekt klasy samochod dopiero jest tworzony...
        //i delegatAutomobilowy jest rowniez null...
        samochodoweZdarzenie sZ = new samochodoweZdarzenie("Zrobiona kierownica", 1, -1, -1);
        if (delegatAutomobilowy != null)
        {
            delegatAutomobilowy(drawInfo);
        }
        for (int i = 1; i < 5; i++)
        {
            sZ = new samochodoweZdarzenie("Zrobione kolo "+i,2,-1,-1);
            _lstKola.Add(new Kolo());
            if (delegatAutomobilowy != null)
            {
            delegatAutomobilowy(drawInfo);
            }
        }
    }
}//koniec klasy samochod

Nie wiem, czy wyraziłem się jasno, generalnie pytanie brzmi: czy możliwe jest wysłanie informacji z konstruktora obiektu (obiektów) aby zaktualizować np progressBar czy statusLabel jeśli obiekt nie został jeszcze zrobiony? Dzięki, że chociaż przebrnęliście do końca pytania. Pewno odpowiedź jest śmiesznie prosta, ale nie potrafię już znaleźć właściwej odpowiedzi...

Pozdrawiam, Bartoles

flag

4 Answers

4

Przy rozwiazaniu ze statycznym eventem nalezy pamietac o odpieciu sie od zdarzenia, poniewaz moga pojawic sie problemy z wyciekami pamieci. W tym konretnym przypadku "klasa Form1" zawsze bedzie "wisiec" w pamieci. Byc moze warto rozwazyc rozwiazanie z przekazeniem delegat do kontruktora.

link|flag
3

Moze jednak lepiej uzyc wzorca Factory zamiast static eventa w konstruktorze obiektu? Tak, wiem, ze w fabryce event tez bedzie statyczny, ale przynajmniej nie bedzie podnoszony z konstruktora:)

class Automobil {}

class AutomobilFactory
{
    public event EventHandler ZbudowanoNowaCzesc;

    private void OnZbudowanoNowaCzesc()
    {
        if(ZbudowanoNowaCzesc != null)
           ZbudowanoNowaCzesc(this, EventArgs.Empty);
    }

    public Automobil Create() //Moze byc public static
    {
        Automobil newMobil = new Automobil();
        OnZbudowanoNowaCzesc();
        newMobil.Kierownica = new Kierownica();
        OnZbudowanoNowaCzesc();

        return newMobil;
    }
}
link|flag
0

Zrób tego event'a statycznym, wtedy nie będzie problemu z podpięciem się przed utworzeniem jakiejkolwiek instancji tej klasy.

public static samochodowyDelegat delegatAutomobilowy;
link|flag
0

Wiedzialem że rozwiązanie nie może być trudne.
Jasne jak słońce! Wielkie dzięki, działa bez zarzutu!

Bartoles

link|flag
No to proszę o zaznaczenie, że jest to prawidłowa odpowiedź :). Taki ptaszek koło odpowiedzi :) – Paweł Łukasik Feb 27 at 21:19

Your Answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.