Dynamiczna zmiana zawartości okna Form


(Nowypunktwidzenia) #1

Wiem, że zadaję dużo pytań - dlatego wytrwałym dziękuję (myślę, że to już ostatnie) :slight_smile: Myślę, że lepiej zapytać niż udawać, że coś się wie, albo siedzieć cicho i o nic nie pytać.

Wracając do tematu - załączam na początek obrazek problemu :

80442915.th.jpg

Pytanie 1.

Zastanawiam się nad stworzeniem Form, w którym po lewej stronie byłoby pole z niezmiennymi przyciskami, natomiast po prawej stronie zmieniałaby się treść w zależności od tego który przycisk z menu po lewej wybraliśmy - całość odbywałaby się właśnie na 1 formie.

Zakładam, że po prawej stronie będzie nie tylko treść tekstowa, ale także różne kontrolki (buttony, edittexty itp...).

I teraz pytanie - jak zrobić, aby ta treść (na tym samym formie) zmieniała się w zależności od tego co wybierzemy z menu po lewej.

Rozwiązanie na które wpadłem, to może by tak w jakiś sposób stworzyć grupy obiektów i je ukrywać i pokazywać w zależności od tego kto wybrał co z menu - ale po pierwsze jak zgrupować takie obiekty (czy służy do tego wyłącznie komponent panel - czy może jakoś inaczej) , a po drugie jak będę wsadzał te komponenty do form i układał w podobnych miejscach dla każdego z podmenu - to mi się wszystko zleje na "kupę" i nie będę widział np. tych pod spodem ....

chyba, że jest gdzieś opcja w Visual Studio aby ukryć widok tych komponentów (a nie przesuwać jako bring i send to front), które wstawiłem - na czas układania innych (tylko tak abym je mógł później wyświetlić)....

Co radzicie - jak wykonać takie menu ze zmienną treścią w środku Form ?

Pytanie2:

Mam jeszcze takie małe nawiązanie do połączenia z bazą danych (MySQL).

Baza danych będzie relacyjna, zbudowana z kilku tabel i teraz zastanawiam się - czy pobierać wszystkie wartości z bazy danych (bo chcę je wyświetlić w programie) i zapisywać je do tablicy obiektów (stworzę jakąś klasę o polach takich samych jak w bazie danych), czy może zrobić strukturę i także tablicę do niej ?

A potem gdy będę chciał wyświetlić imię jakiejś osoby np. w labelu to wyciągnę z obiektu np. osoba[1].imie i wpisze je właśnie do tego labela ? Dobry pomysł - czy może też zrobić to inaczej ?

Jeżeli to coś zmieni - to chciałbym także te informacje zapisywać do pliku, tak aby program miał w zanadrzu bazę danych w przypadku braku połączenia z internetem (offline).


([alex]) #2

Ad.1. Po lewej Wstawiasz Panel z Dock - Left. Po prawej wstawiasz kilka TPanel, każdy ma Dock - Fill. Na każdy wstawiasz własne komponentu. Wszystkie oprócz jednego są schowane.

Po naciśnięciu czegoś po lewej chowasz wszystkie po prawej Hide ujawniasz jeden po prawej Show.

Ad.2. Poszukaj komponentu Midas, robi to automagicznie.


(Somekindsoftware) #3

Powinieneś zrobić sobie obiekty UserControl, na nich umieścić swoje komponenty, a potem wyświetlać w zależności od potrzeb. UserControl jest taką właśnie grupą kontrolek w formie oddzielnej od Form klasy, więc ma swojego designera, itd.

No cóż, wybrałeś sobie chyba najgorszą z możliwych baz, więc będziesz miał trudniej niż mogłoby być. Tylko co nazywasz strukturą?

Ogólnie to, co chcesz zrobić nazywa się ORM (Object-relational Mapping) i są do tego gotowe biblioteki, np. Microsoftowe LINQ to SQL czy Entity Framework, dostępne jako części .NET, ale one nie współpracują z MySQL. Jest nHibernate, który jest największą kobyłą w branży, więc pewno współpracuje z MySQL. Ale może są też inne gotowe biblioteki do znalezienia w internecie.

Pomysł dobry, tylko skąd Ty masz tyle czasu, żeby wszystko robić ręcznie? :slight_smile:

Do wiązania obiektów z kontrolkami WinForms najlepiej użyć DataSource. Dodajesz nowe DataSource typu Object i wybierasz w nim swoją klasę, wówczas na liście w okienku Data Sources możesz skonfigurować jakiego typu kontrolkę chcesz powiązać z którą właściwością, potem przeciągasz na Form/UserControl i wszystkie kontrolki do wprowadzania danych masz wygenerowane automatycznie. Również automatycznie powstaje obiekt BindingSource, który pozwala na zapisywanie zmian między danymi wpisanymi przez użytkownika do formatki, a danymi w obiektach danych.

Jeżeli będziesz miał jakąś strukturę obiektów, to możesz ją zserializować do pliku np. w formacie XML.


(Nowypunktwidzenia) #4

Odnośnie tworzenia własnych kontrolek to znalazłem jakiegoś tutka - zobaczymy jak to będzie :slight_smile:

A wracając do bazy danych - to dlaczego mysql to najgorsza ? Dodałem do bazy mysql connector i za pomocą jego będę się łączył z bazą danych.

Założyłem sobie bazę danych już w internecie na darmowym hostingu, a tabelę będę tworzyć w jakimś odrębnym programie np. power designerze, a potem wkleje kod do wygenerowania tabel.

Jestem nowicjuszem w tym temacie i gdybyś wytłumaczył mi trochę jaśniej - w takim razie zrezygnować z mysql i wziąć inną bazę danych czy co (jeżeli tak to jaką, chciałbym mieć ją gdzieś w internecie) ?

Dlaczego myślisz, że to zajmie dużo czasu tzn. w/w pomysł - jak to skrócić bo nie bardzo zrozumiałem :slight_smile:


(Somekindsoftware) #5

Ja bym wolał już PostgreSQL niż MySQL z uwagi na jaśniejsze zasady licencjonowania, cenę i lepszą zgodność ze standardami. Nie chcę tu jakiegoś flamewara toczyć, jeśli bardzo chcesz tego MySQLa, to go używaj.

Bo ręczne tworzenie kontrolek, przypisywanie wartości z obiektu do kontrolek przy wczytywaniu, a potem z powrotem przy zapisywaniu jest żmudne, błędogenne i pracochłonne. Dlatego polecam użycie DataSource z BindingSource w celu zautomatyzowania tego procesu.

Tutaj możesz poczytać o tym: http://msdn.microsoft.com/en-us/library/6ckyxa83.aspx

Do tego użycie ORM sprawiłoby, że nie musisz ręcznie tworzyć zapytań SQL i ich wywoływać, bo obiekty byłyby mapowane na tabele automagicznie - powiązania właściwości z kolumnami definiuje się po prostu w pliku XML. Poza tym nie bawisz się w ręczne zarządzanie połączeniami, itd.

Na początek: http://sharp.jogger.pl/2007/09/22/nhibe ... -tutorial/ A tutaj nawet coś o użyciu z MySQL: http://geekswithblogs.net/pariam/archiv ... 86352.aspx

Z tymże, zgranie tego wszystkiego do kupy może być trudne dla początkującego, za to pozwala zaoszczędzić na czasie.


(Nowypunktwidzenia) #6

Wracam do tematu, ale mam problem - chodzi o zmianę zawartości okna form tak jak to pisałem w 1 poście.

W oknie projektowania (Designer), gdybym chciał używać opcji visible, albo Hide (do ukrywania kontrolek) to i tak muszę nałożyć jedną na drugą - gdy chcę je wyświetlić w tych samych miejscach - co jest bardzo nieeleganckie i bardzo łatwo pomylić się w przypadku dużej liczby kontrolek (nawet gdy stworze user control).

Jak w takim razie poradzić sobie ze zmianą treści w Formie ( tak aby część została stała = menu i po naciśnięciu jakiegoś przycisku zmieni się ona ...- ale odpada raczej visible - przynajmniej w tej formie jak napisałem wyżej).

Jest na to jakiś sposób ?


(Somekindsoftware) #7

W designerze projektujesz Form z Menu i Panelem pod Menu, oraz kilka swoich UserControl. Resztę robisz programowo w ten sposób:

1) Po wciśnięciu przycisku tworzysz nowy obiekt swojej UserControl.

2) Ustawiasz mu Dock na Fill.

3) Czyścisz kolekcję kontrolek Panela (czyli usuwasz poprzednio wyświetlaną kontrolkę) nazwaPanela.Controls.Clear().

4) Dodajesz nową kontrolkę do kontrolek Panela przez nazwaPanela.Controls.Add(TwójUserControl).


(Tomek Matz) #8

Możesz też ładować te wszystkie UserControl w zdarzeniu Load Form-y. Uchwyty do tych UserControl przechowuj jako prywatne pola klasy danej Form-y. Wszystkie UserControl będą miały właściwość Visible ustawioną na false, wszystkie za wyjątkiem tej, która w danym momencie ma być wyświetlona. Dzięki takiemu rozwiązaniu będziesz miał cały czas dostęp do danych, które użytkownik wprowadził w kontrolkach danej UserControl (bo będą one przechowywane w pamięci operacyjnej), mimo tego, że nie będą już wyświetlane na ekranie. W zdarzeniach Click poszczególnych przycisków będziesz po prostu ustawiał wybrany UserControl na Visible true, a pozostałe na false. Dodam jeszcze, że zamiast ustawienia ww. Dock na Fill możesz tak zaprojektować te UserControl, żeby ich rozmiar był zgodny z rozmiarem panel-a, w którym zostaną umieszczone. Niech każdy UserControl dziedziczy po jakiejś Twojej klasie MyUserControl (która dziedziczy po klasie UserControl), której zdefiniujesz właściwość Size i być może jeszcze jakieś inne, które mają być wspólne dla wszystkich Twoich UserControl.


(Somekindsoftware) #9

Tylko czy jest sens tworzyć obiekty, które mogą nigdy nie zostać wykorzystane i spowalniać ładowanie głównego okna? Już lepiej nie tworzyć nowej UserControl przy każdym kliknięciu, a tylko przy pierwszym, a w międzyczasie przechowywać ją w polu klasy Form.

Można i tak, chociaż kontrolki GUI to nie jest najlepsze miejsce na przechowywanie danych.

Zamiast? Zadziała tak samo jak Fill po zmianie rozmiaru okna?


(Tomek Matz) #10

Jeśli faktycznie ładowanie głównego okna będzie w zauważalnym stopniu spowolnione (kiedy taka sytuacja wystąpi?), to oczywiście można przenieść tworzenie poszczególnych UserControl do procedur Click. Wracając do tego co napisałeś o tworzeniu/niszczeniu za każdym razem UserControl ... Uzasadnienie jakie widzę dla takiego rozwiązania to chęć napisania programu zużywającego RAM w minimalnym stopniu. Czy właśnie tym się kierowałeś?

Chodziło o tymczasowe przechowywanie danych. Użytkownik otwiera okno, kontrolki w poszczególnych UserControl dostają domyślne wartości (np. wczytane z pliku konfiguracyjnego aplikacji), użytkownik edytuje różne kontrolki w różnych UserControl, kończy edycję, tworzony jest obiekt, który jest wypełniany wartościami z tych różnych kontrolek (jeśli użytkownik kliknie Cancel to obiekt oczywiście nie jest tworzony). To, że kontrolki nie służą do przechowywania danych to ja bardzo dobrze wiem :slight_smile: Podsunąłem sugestię, że jeśli zostanie zrobione to w sposób przeze mnie wyżej opisany, to można je wtedy użyć jako tymczasowe źródło danych.

Jedyne co robi Dock Fill to wypełnia przestrzeń kontenera poprzez zmianę rozmiaru kontrolki (w tym wypadku UserControl). Położenie kontrolek w obrębie danego UserControl nie ulega zmianie. Ustawiając sobie Size danego UserControl na taki jak ma Panel (w którym zostanie on umieszczony) można lepiej rozmieścić poszczególne kontrolki. Nie dojdzie więc do sytuacji, że w lewym górnym rogu panelu będzie nagromadzenie kontrolek, a cała reszta dostępnej przestrzeni będzie pusta. Działa to też w drugą stronę ... nie dojdzie do sytuacji, że rozmiar projektowanej UserControl okaże się większy niż rozmiar Panel-a (oczywiście można pomyśleć nad zastosowaniem scrollbar-ów). Z góry narzucamy sobie ograniczenie, którego trzeba się trzymać.


(Nowypunktwidzenia) #11

Somekind - twój post naprawdę mi pomógł - ten sposób faktycznie działa !

Jest tylko jedno "małe" ale ;D Co w przypadku gdybym nie chciał tworzyć własnych kontrolek, ale do Panelu wrzucać np. kilka kontrolek z listy toolbox (komponentów dostępnych w Visual Studio) - w tym przypadku, przy dynamicznym tworzeniu np. Button przycisk = new Button(); - tak naprawdę nie wiem gdzie ten przycisk się pojawi w Panelu, ponieważ "fizycznie" go na podglądzie nie widzę (w oknie Designera).

Czy jedynym wyjściem jest "strzelanie" we właściwości location tzn. przycisk.Location = new Point(X, Y); ??

Zastanawiałem się jeszcze nad użyciem komponentu TabControl - tam mam kolejne zakładki, do których mogę za pomocą designera wrzucać komponentu (drag & drop) - tylko czy da się zrobić tak, aby pozostałe zakładki nie były widoczne tzn. żeby aktualnie była widoczna tylko 1 ????

Matzu - czyli w Load Formy także robię Button przycisk = new Button(); i jego właściwość visible jest automatycznie ustawiona na False ?

Twoje rozwiązanie może byłoby dobre, bo zależałoby mi na utrzymaniu w kontrolkach tego co zostało wpisane .... rozumiem, że tutaj także ustawiam Panel na środku i w momencie gdy chcę wyświetlić kontrolkę to dodaję ją do Panelu a gdy chcę wyświetlić inną to najpierw kasuję za pomocą Clear to co było w panelu a potem dodaję nową ?? Bo nie bardzo widzę, aby samodzielnie nadawać wszystkim kontrolko visibility na hidden a potem jednej na visible.

A możesz mi jeszcze wyjaśnić w jaki sposób przechowywać uchwyty do tych UserControl ? Przykładowy kod ....

Bo w momencie gdy tworzę kontrolki po naciśnięciu przycisku za pomocą Button przycisk = new Button(); i gdy skasuję je po przyciśnięciu czegoś innego w menu i gdy wrócę do poprzedniego menu - to nie mam np. w polach editbox wpisanego tego co chciałem .... nie wiem jak to rozwiązać, czy dać tam If'a - który sprawdza czy przycisk został naciśnięty 1 raz tzn :

private object obiekt;

        private bool liczba = false;


        private void button1_Click(object sender, EventArgs e)

        {


            if (liczba == false)

            {

                TextBox tekst = new TextBox();

                obiekt = tekst;

                liczba = true;

            }


            panel1.Controls.Add((TextBox)obiekt);

        }

Czy może to zapisać inaczej - lepiej ??? Bo w/w sposób także działa....Chyba, że jest jakieś zdarzenie wychwytujące tylko 1 kliknięcie w przycisk ..?

Aha a wracając do ustawień size (rozmiaru komponentów) to w dziedziczeniu ma zrobić coś takiego np.

partial class UserControl1 : Form1 - tylko czy mogę dziedzić np. po Panelu bo chciałbym, żeby moja kontrolka (user control1) dziedziczyła wymiar Panela - była do niego dopasowana....

Czy UserControl może dziedziczyć tylko po Usercontrol albo Form - bo Panel1 (mam nałożony na formie) a nie mogę z niego dziedziczyć...

Jeszcze raz dzięki za tak rozbudowaną i konstruktywną pomoc - teraz mi dużo wyjaśniła :slight_smile:


(Tomek Matz) #12

Przygotowałem przykładowy projekt http://www.speedyshare.com/files/30934416/UserControlDemo.zip. Myślę, że dokładnie zobrazuje co miałem na myśli.

Jeśli chodzi o to dziedziczenie to miało to wyglądać tak:

MainUserControl : UserControl

UserControl1 : MainUserControl

UserControl2 : MainUserControl

itd.

W MainUserControl ustawiasz rozmiar na dokładnie taki sam jak rozmiar Panel-a, w którym będą umieszczane poszczególne UserControl (1,2, itd.). W MainUserControl możesz też sobie zdefiniować jakieś protected kontrolki (ja zrobiłem przykładowy label), które będą wspólne dla wszystkich UserControl (1, 2, itd.).


(Nowypunktwidzenia) #13

Przeanalizowałem twój kod - wszystko działa jak ma działać, ale mam kilka pytań :

1.

MainUserControl mainUserControl = (MainUserControl)((Button)sender).Tag;

Do czego jest ta linijka w kodzie ? Nie mogłoby być po prostu userControl1.visible = true;?

Podejrzewam, że tutaj chodziło właśnie o to dziedziczenie - żeby przejąć ustawienia rozmiaru okna - ale gdybyś to wyjaśnił :stuck_out_tongue:

Z tego co widzę, to każda zrobiona przez ciebie kontrolka ma wymiary takie jak panel na Formie - w takim razie nie potrzebne jest tutaj chyba dziedzicznie ?

Aha i do czego służy właściwość Tag - do przetrzymywania referencji ?


(Tomek Matz) #14

Mogłoby być. Sęk w tym, że wtedy musiałbyś dla każdego UserControl ustawiać to osobno, a tak wszystko załatwione jest w dwóch linijkach kodu. Nawet, gdy dodasz kolejne UserControl na Form-ę to nie będziesz musiał tego zmieniać. No ale jak chcesz sobie ustawiać dla każdego osobno to oczywiście możesz.

Każdy UserControl ma taki rozmiar jak Panel, dzięki temu, że każdy UserControl dziedziczy po MainUserControl, w którym ustawiłem ten rozmiar. Czyli wystarczyło ustawić w jednym miejscu (na tym polega dziedziczenie). Możesz sobie ustawić dla testu inny Size w MainUserControl, skompiluj projekt i zobacz co się stanie z rozmiarem wszystkich UserControl (1,2, itd.).

Tak, Tag użyłem do przechowywania referencji do danej UserControl. Dzięki temu wiem jakiej UserControl tyczy się dany Button.


(Somekindsoftware) #15

Jeśli jest kilka różnych UC, na każdej kilkanaście innych kontrolek, a do tego jeszcze jakieś operacje, to już może to być odczuwalne.

No i nie ma żadnego znaczenia, czy to będzie zauważalne czy nie, po prostu nie ma sensu robić czegoś, co nie będzie potrzebne.

Serio takie coś pisałem? Nie przypominam sobie. Na pewno nie chodziło mi tu o jakieś niezauważalne skrawki pamięci RAM, dałem tylko prostą odpowiedź na proste pytanie, bez zagłębiania się w szczegóły wydajnościowe, które wyszły dopiero po Twoim poście. :slight_smile:

Chodziło o tymczasowe przechowywanie danych. Użytkownik otwiera okno, kontrolki w poszczególnych UserControl dostają domyślne wartości (np. wczytane z pliku konfiguracyjnego aplikacji), użytkownik edytuje różne kontrolki w różnych UserControl, kończy edycję, tworzony jest obiekt, który jest wypełniany wartościami z tych różnych kontrolek (jeśli użytkownik kliknie Cancel to obiekt oczywiście nie jest tworzony). To, że kontrolki nie służą do przechowywania danych to ja bardzo dobrze wiem :slight_smile:

Tymczasowe, czyli na czas ich wprowadzania, do momentu zapisu albo anulowania. Potem te dane nie są już do niczego potrzebne.

Po wykorzystaniu rozwiązania z jednorazowym tworzeniem UC scenariusz działania będzie taki:

1) Tworzona i otwierana jest pusta kontrolka.

2) Użytkownik wypełnia pola danymi.

3) Użytkownik anuluje edycję.

4) Za jakiś czas użytkownik ponownie uruchamia kontrolkę i... WTF? Jakieś dane już tam są? Ale skąd, po co i dlaczego?

A jeśli ma nie dochodzić do takiej sytuacji, to trzeba ręcznie zaimplementować czyszczenie wszystkich kontrolek edycyjnych przy zamykaniu UC. Po co tracić czas?

Ok, może ktoś takiego dziwnego zachowania akurat potrzebuje... Chociaż nie spotkałem się z tym nigdy. :slight_smile:

Oczywiście, że nie. Ale od tego jest Anchor kontrolek, a nie Size dla UserControl.

Oczywiście, że dojdzie. Jeżeli nie ustawisz, że UserControl ma wypełniać Panel (czyli Dock = Fill), to cały czas będzie trzymała swój rozmiar w jego lewym górnym rogu.

W ramach UserControl trzeba ustawić odpowiednie typy Anchor poszczególnym kontrolkom, a całemu UserControl dać Dock na Fill, żeby GUI zachowywało się sensownie.

W takiej sytuacji zamiast Panel lepiej użyć TableLayoutPanel albo FlowLayoutPanel, które potrafią w miarę sprytnie układać kontrolki obok siebie i nie trzeba ręcznie liczyć Location. TabControl służy do czegoś całkiem innego. :slight_smile:

Do tego służą pętle. :wink:

Sprawdź po prostu, czy TextBox nie jest nullem, a jeśli jest, to go utwórz. A potem wyświetl. I żadna dodatkowa zmienna typu bool nie jest Ci do tego potrzebna.

Ogólnie można dziedziczyć po Panelu, tylko Ty tego nie potrzebujesz. Zauważ, że UserControl to taki Panel do umieszczania innych kontrolek.

-- Dodane 26.10.2011 (Śr) 20:10 --

To jest jakieś dziwne powiązanie między obiektami, które nie jest zbyt przejrzyste, łatwo o nim zapomnieć, a do tego wymaga sporo rzutowań.

Za sterowanie widokiem, czyli decyzję o tym, którą kontrolkę wyświetlić po naciśnięciu którego przycisku powinno odpowiadać główne okno, bo to ono jest tutaj kontrolerem widoku, a nie jakaś właściwość przycisku.

Użyłbym tu raczej Dictionary i w nim skonfigurował te zależności. Dzięki temu będą w jednym miejscu, na dodatek w klasie do tego przeznaczonej. Wówczas, w celu wyświetlenia wybranej UC wystarczy w kodzie obsługi kliknięcia dać: dict[((Button)sender)].Show();


(Tomek Matz) #16

Po lewej stronie okna masz przyciski, a po prawej UserControl. Użytkownik klika przycisk nr 1 i wyświetla mu się UserControl nr 1. Wprowadza tam jakieś zmiany. Później klika przycisk nr 2 i wyświetla mu się UserControl nr 2. Wprowadza tam jakieś zmiany. Teraz wraca do przycisku nr 1. Wyświetla mu się UserControl nr 1. Przy czym tym razem wyświetlają mu się wartości, które przed chwilą tam wprowadził (a nie domyślne), chociaż jeszcze ich nigdzie nie zapisał. Zapis może wykonać po zakończeniu edycji wszystkich UserControl, ale przecież nie musi. Reasumując edycja nie tyczy się jednej UserControl, a wszystkich. Nie można robić tak, że w trakcie edycji gubione są po drodze zmiany wprowadzone przez użytkownika w którymś z UserControl.

W jaki sposób ma do tego dojść? Przecież rozmiary Panel oraz UserControl są identyczne (są ustawione na sztywno, nie można ich zmieniać, rozmiar okna się nie zmienia). Dock Fill jest konieczne, ale tylko i wyłącznie wtedy, gdy możliwa jest zmiana rozmiaru okna.

Ustawiane to jest w jednym miejscu (w zdarzeniu Load Form-y) i wymaga dwóch rzutowań.

Pewno, słownika można użyć. Dodatkowe pole klasy, ale jedno rzutowanie mniej. Może faktycznie jest to bardziej przejrzyste rozwiązanie. BTW mógłbyś powiedzieć czemu referencję do obiektu używasz jako klucz tego słownika? Ja bym tutaj użył właściwości Name danego Button-a.

I na koniec :slight_smile: Żeby kontynuowanie tej dyskusji miało sens IMO potrzebna jest informacja o tym do czego będzie używane to okno przez autora tematu (tzn. jakie będzie jego przeznaczenie w aplikacji, czy to będzie okno, którego rozmiar można zmieniać, czy tez nie). Ja cały czas pisząc mam przed oczami okno/a ustawień.

-- Dodane 26.10.2011 (Śr) 22:37 --

Wprowadziłem drobne zmiany w kodzie http://www.speedyshare.com/files/30940508/UserControlDemo.zip. Zamiast Tag jest używany słownik, a wyświetlanie danego UserControl odbywa się dopiero w momencie kliknięcia danego przycisku. Tworzenie UserControl (czytaj wywołanie konstruktora) pozostawiłem w zdarzeniu Load, bo moim zdaniem nie jest to czasochłonna operacja (a przynajmniej nie dla zaledwie kilkudziesięciu kontrolek).


(Somekindsoftware) #17

Rozumiem takie podejście, chociaż ja zamiast Buttonów użyłbym w takiej sytuacji do przełączania między poszczególnymi widokami TabControl albo jakiegoś TreeView, byłoby to bardziej czytelne i zgodniejsze z konwencjami w innych programach.

Zauważ, że w sytuacji, którą opisałeś, wszystkie UserControl stanowią tak naprawdę interfejs do edycji jednej całości (być może obiektu, być może kilku powiązanych ze sobą). Ja w poprzednich postach zakładałem, że jedna UserControlka służy do edycji jednej całości, np. jest formularzem dodawania do bazy nowego klienta. Wówczas po jej zamknięciu wprowadzone dane są albo zapisywane albo porzucane, ale nie ma potrzeby do nich wracać. W takim przypadku lepiej tworzyć UC przy każdym otwieraniu.

A ktoś stwierdził, że jest zabroniona? Coś przeoczyłem? Jeśli tak, to masz rację, nie trzeba robić Fill, wydawało mi się po prostu, że o pełnowartościowych okienkach mówimy.

I pamiętania o tym. I pamiętania o tym, że Tag już jest zajęty i, żeby go czasem nie użyć do czegoś innego. I w ogóle pachnie trochę jak spaghetti. :wink:

Słownik o jakiejś czytelnej nazwie, która od razu mówi, do czego służy, kontra pole Tag, które jest śmietnikiem typu object na cokolwiek i może zostać użyte w dowolnym momencie na coś innego... Zdecydowanie bardziej przejrzyste. :slight_smile:

Bo Button na pewno istnieje i ciągle jest tym samym Buttonem, a poza tym nie ma dwóch takich samych Buttonów. A z napisem, to nigdy nic nie wiadomo, może go nie być, może się zmieniać, a co gorsze, mogą być dwa Buttony o tej samej nazwie i całe rozwiązanie leży.

A ja okno Firefoxa. :stuck_out_tongue:

A tak na serio, myślałem o bardziej ogólnych przypadkach niż ustawienia, bo te faktycznie rządzą się specyficznymi prawami.


(Tomek Matz) #18

To nie ma znaczenia czego się użyje :slight_smile: Ważne, żeby to coś było klikalne. Może to być TreeView, ListView, a może to być Button (tekstowy lub obrazek). Zobacz menu w np. MS Office -> Opcje programu Excel lub Word. Tam właśnie użyto takich zwykłych button-ów.

Takie też nabrałem podejrzenia po ostatnim Twoim poście, dlatego też na końcu swojego ostatniego posta napisałem, że kontynuowanie tej dyskusji będzie miało sens dopiero wtedy, gdy będziemy mieć pewność co do przeznaczenia tego okna.

Nie, nie było mówione. Tak założyłem. Być może błędnie. Zobaczymy co powie autor tematu.

Słuszna uwaga, ja sobie przyjąłem, że Name będzie zawsze unikalne (nie wiem skąd mi się to wzięło). Tymczasem to Visual Studio narzuca, że w obrębie kontenera dwie te same kontrolki nie mogą mieć tej samej nazwy, ale już w kodzie taką zmianę można wprowadzić (jeszcze sprawdzałem dokumentację dla pewności). Pytanie tylko, po co ktoś miałby w kodzie taką zmianę wprowadzać. Co do tej referencji ... Zastanawiam się, czy jednak nie trzeba tutaj przeciążyć tego GetHashCode i Equals? Czy aby na pewno zawsze zadziała to tak jak trzeba?


(Somekindsoftware) #19

Niby zwykłych, ale jakoś tak ładniej wyglądają, bardziej jak menu niż 5 przycisków rzuconych na Formę. :wink:

Nie tyle VS narzuca, co designer tak robi.

A po co ktoś miałby robić SQL Injection... Nie zabezpieczajmy się. :wink:

Raczej niewielkie są szanse na to, aby dwa różne Buttony miały ten sam adres w pamięci.


(Tomek Matz) #20

Kwestię wyboru kolorów itp. pozostawiam zawsze grafikom (albo ludziom, którzy mają do tego wyczucie). Ja niestety nie mam do tego głowy i raczej nie bawię się w modyfikację domyślnego wyglądu kontrolek. Oczywiście zgadzam się z tym, że tam wygląda to o wiele ładniej.

Nie wydaje mi się, aby porównanie tego z SQL Injection miało sens. Jeśliby wystąpiła sytuacja, że dwie kontrolki mają tą samą nazwę, to taki błąd można bardzo łatwo wychwycić.

Bardziej chodziło mi o sytuację, że zmieni się adres w pamięci danego Button-a. Sęk w tym, że nie wiem, czy jest to w ogóle możliwe. W końcu całe zarządzanie pamięcią odbywa się w tle.