Użycie Lablea przez klasę w WinForms

Użycie Lablea przez klasę w WinForms
RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

Cześć

Mam podstawowy projekt w Windows Forms

Kopiuj
public partial class MainForm : Form
{
...
}

MainForm zawiera jakieś tam Labele. Wszystkie są ustawione jako public.
Do tego mam klasę - dajmy na to T1 - w osobnym pliku i chciałbym, aby ona korzystała z tych Labeli.
Zauważytłem, że jeżeli tworzę obiekt klasy T1 bezpośrednio w:

Kopiuj
MainForm : Form

to ona tych Labeli nie widzi, widzi je, gdy utworzę obiekt w:

Kopiuj
public MainForm()

ale wtedy, aby metoda klasy T1 korzystała z Labela musi go mieć przekazanego jako argument (a to nie będzie jeden Label tylko więcej). I to każda metoda osobno, nawet przekazanie jako argument konstruktora nie pomaga.
Jest jakiś sposób na to czy może powinienem tworzyć obiekty w

Kopiuj
public MainForm()

?
Klasa T1 nie jest pochodną MainForm.

Sorry za formatowanie, ale nie ogarniam tego i proszę mi nie tłumaczyć, że T1 i MainForm to są osobne klasy, bo tyle to wiem.

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

Kurde, chyba sam ogarnąłem 😄
KLasa T1 była zadeklarowana jako partial class T1. Dodałem public i chyba działa.

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

Albo może i nie?

AdamWox
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Jastrzębie-Zdrój
  • Postów: 2180
1

Przekaż całe MainForm do T1, będziesz miał dostęp do wszystkich publicznych pól i zmiennych

Kopiuj
public class T1
{
  Form _frm;
  public T1(Form frm)
  {
    _frm = frm;
  }
}

a w MainForm

Kopiuj
T1 t1 = new T1(this);
RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

Działa, ale musiałem dać:

Kopiuj
MainForm _frm i
public T1(MainForm frm)

I przy okazji rozwiązała się druga kwestia. Muszę tworzyć obiekt T1 w public MainForm(), bo inaczej się nie kompiluje.

AdamWox
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Jastrzębie-Zdrój
  • Postów: 2180
0

Nie musisz tworzyć obiektu T1 w MainForm(). Tworzysz obiekt T1 tam gdzie jest ci on potrzebny. Pokaż, gdzie stworzyłeś obiekt T1? I dlaczego "nie działa" Form frm skoro MainForm dziedziczy po Form?

PS.
Mam wrażenie, że nie rozumiesz co robisz, a już tym bardziej nie znasz struktury projektu WinForms. Nie wiem jaki jest cel przekazywania całego okna do innej klasy, nie wiem jaki jest cel mieć dostęp do labelek z głownego okna. Dobrze by było opisać problem, bo może (a nawet na pewno) podchodzisz to swojego problemu źle 🤔

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
1

Zgaduję, że chodzi o przeniesienie jakiejś logiki z klasy formularza na zewnątrz, co jest słuszną ideą. Niemniej jednak, zamiast wiązać na sztywno te klasy ze sobą, lepiej zastosować wzorzec MVP (Model-View-Presenter), który w skrócie działa tak, że Presenter operuje (wysyła i odbiera dane) do View, który jest implementowany przez Form.
Dzięki temu mamy kod, który: oddziela logikę od zarządzania GUI, jest testowalny i pomijamy dziwne problemy typu konstruktor formularza zaczyna się nam łączyć z bazą, i designer się wywala.

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0
AdamWox napisał(a):

Nie musisz tworzyć obiektu T1 w MainForm(). Tworzysz obiekt T1 tam gdzie jest ci on potrzebny. Pokaż, gdzie stworzyłeś obiekt T1? I dlaczego "nie działa" Form frm skoro MainForm dziedziczy po Form?

PS.
Mam wrażenie, że nie rozumiesz co robisz, a już tym bardziej nie znasz struktury projektu WinForms. Nie wiem jaki jest cel przekazywania całego okna do innej klasy, nie wiem jaki jest cel mieć dostęp do labelek z głownego okna. Dobrze by było opisać problem, bo może (a nawet na pewno) podchodzisz to swojego problemu źle 🤔

Rozumiem co robię, ale rzeczywiście - struktury projektu WinForms nie znam. Dopiero poznaję.
Jak wpisałem jak podałeś Form _frm to mam 'Form' does not contain a definition for 'lbl1' and no accessible extension method 'lbl1' accepting a first argument of type 'Form' could be found (are you missing a using directive or an assembly reference?) i też mnie to zastanawia czemu, skoro MainForm dziedziczy po Form. W tej chwili wpisanie MainForm załatwiło sprawę i mnie to zadowala.
I teraz mam klasy T1 i P1 w osobnych plikach (nie dziedziczą po MainForm) i coś takiego:

Kopiuj
   {
       List<int> STable = new List<int>();
       List<P1> P1s = new List<P1>();
...
}

W konstruktorze T1 mam te dwie listy oraz Form a właściwie MainForm przekazane przez this jak podałeś (wcześniej nie miałem).
Teraz jeżeli piszę:

Kopiuj
public partial class MainForm : Form
{
  P1 p1 = new P1();
  P1 p2 = new P1();
  List<int> STable = new List<int>();
  List<P1> P1s = new List<P1>();

  //T1 t1 = new T1(ref P1s, ref STable, this);

  public MainForm()
        {
            InitializeComponent();
            GoFullscreen(false);
 
            T1 t2 = new T1(ref P1s, ref STable, this);
      }
}

to działa, mogę też dodać kolejny obiekt T1 t3 w MainForm_Load(object sender, EventArgs e), ale jak odkumentuję T1 t1 to mam:
A field initializer cannot reference the non-static field, method or property 'MainForm.P1s' , to samo dla STable a chcę mieć referencje, bo nie będę za każdym razem kopii robił. T1 ma modyfikować pola obiektów P1 w P1s (są zawarte odpowiednie metody) i cyferki w STable oraz Keyword 'this' is not available in the current context. A jeszcze dodam, że ja przerabiam projekt, który jakiś czas temu napisałem w C++ w konsoli i tam działał, tylko, że to wszystko mało przejrzyste było, wszystko w linijkach na czarnym ekranie wypisywać. Teraz próbuję to przerobić na fajny projekt z GUI, ale bezboleśnie to póki co nie przechodzi :)

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
2

Do tego mam klasę - dajmy na to T1 - w osobnym pliku i chciałbym, aby ona korzystała z tych Labeli.

Nie idź tą drogą. Zdefiniuj metodę w MainForm która robi na labelach to co powinna. Z drugiej klasy wywołuj tę metodę.

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

No i co, wszyscy ucichli?

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
2
Radziu napisał(a):

Jak wpisałem jak podałeś Form _frm to mam 'Form' does not contain a definition for 'lbl1' and no accessible extension method 'lbl1' accepting a first argument of type 'Form' could be found (are you missing a using directive or an assembly reference?) i też mnie to zastanawia czemu, skoro MainForm dziedziczy po Form. W tej chwili wpisanie MainForm załatwiło sprawę i mnie to zadowala.

Oczywistym jest, że pole jest zdefiniowane w tej klasie, w której jest, a nie w bazowej. Rodzic nie ma skąd (ani po co) wiedzieć o polach swoich dzieci. MainForm dziedziczy z Form i dodaje swoje pola, więc taki np. lbl1 jest w MainForm, a nie w Form.
Obstawiam, że @AdamWox po prostu skrót myślowy zastosował pisząc o Form.

jak odkumentuję T1 t1 to mam:
A field initializer cannot reference the non-static field, method or property 'MainForm.P1s'

No tak, to prawda. Nie możesz inicjalizując pole odwoływać się do innych niestatycznych pól.
Możesz sobie zadeklarować pole w klasie, i zainicjalizować je w konstruktorze, o tak:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
    }
}

Bez ref, bo są zbędne.

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

No właśnie. I dlatego ja sobie wpisywałem MainForm _frm i mi to w niczym nie przeszkadzało. Jeśli chodzi o refy to gdzieś w książce wyczytałem, że obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego a to, że mam je w wielu miejscach wynika z tego, że przepisuję ten projekt z c++ i ref pojawił się tam gdzie był &, ale rozumiem, że mogę tego się spokojnie pozbyć.
Co się tyczy pól niestatycznych - póki co tworzę obiekty zawsze w jakiejś metodzie i jest dobrze. Takiego czegoś jak tu podałeś z odwołaniem poprzez this nie znałem. Będzie okazja wypróbować. Dzięki za pomoc.

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
1

obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego

Nie ma takiej zasady. W C# są "reference types" i są "value types". Do pierwszych należą klasy (typy zdefiniowane za pomocą słowa class), do drugich struktury (zdefiniowane słowem struct).

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
1
Radziu napisał(a):

No właśnie. I dlatego ja sobie wpisywałem MainForm _frm i mi to w niczym nie przeszkadzało. Jeśli chodzi o refy to gdzieś w książce wyczytałem, że obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego a to, że mam je w wielu miejscach wynika z tego, że przepisuję ten projekt z c++ i ref pojawił się tam gdzie był &, ale rozumiem, że mogę tego się spokojnie pozbyć.

Jak najbardziej.

Co się tyczy pól niestatycznych - póki co tworzę obiekty zawsze w jakiejś metodzie i jest dobrze. Takiego czegoś jak tu podałeś z odwołaniem poprzez this nie znałem. Będzie okazja wypróbować. Dzięki za pomoc.

this podkreśla, że odwołujesz się do elementu klasy. Równie dobrze możesz to słówko pominąć, bo w tym kontekście jasne jest, o które t1 chodzi. (Bo jest tylko jedno. ;))

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 48
0

@somekind po Twoim poście i napisałem coś takiego:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
        T1 t2 = new T1(P1s, STable, this);
        
    }
}

Teraz dowolna metoda należąca do MainForm widzi t1, ale nie widzi t2. Tak się zastanawiam dlaczego, przecież t2 zostało utworzone w konstruktorze, czy to nie jest konstruktor?

AD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 50
2
Radziu napisał(a):

@somekind po Twoim poście i napisałem coś takiego:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
        T1 t2 = new T1(P1s, STable, this);
        
    }
}

Teraz dowolna metoda należąca do MainForm widzi t1, ale nie widzi t2. Tak się zastanawiam dlaczego, przecież t2 zostało utworzone w konstruktorze, czy to nie jest konstruktor?

Nie widzi bo t2 jest zdefiniowane w konstruktorze, a nie w klasie. W momencie zakończenia kodu konstruktora zmienna t2 znika.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.