Windows Forms App w VS C#

0

Witam. Nie potrafię połączyć obiektowego pisania programu z Windows Forms Application. Korzystam z Visual Studio 2008 i piszę w C#.

Bo mam w projekcie tak jakby dwa główne pliki:

Program.cs

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
          
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            
        }
    }
}

i Form1.cs

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

W którym pliku mam tworzyć klasy itp... aby mój program pisany był poprawnie obiektowo z wykorzystaniem okienek ?

Często zdarza się też, że trzeba wyedytować jakąś wartość któregoś atrybutu kontrolki i jak wtedy się odwoływać do formy ? Próbowałem i nie wychodziło mi.

W którym momencie tworzyć obiekty klasy i w jakim pliku ? W jakim miejscu pliku ?

A czy nie da się tworzyć klas i dołączać je przy pomocy include lub czegoś innego ?

Proszę o jakieś wyjaśnienie, bo próbowałem coś skleić ale nie działa mi.

Dodam tylko, że potrafię obsługiwać kontrolki i formy, ale nie obiektowo, czyli wiem co i jak, ale nie do końca z pełnowartościowym kodem :)

0
  1. Ja raczej skłaniam się do podejścia jedna klasa w jednym pliku, dlatego dodatkowe klasy dodaję w kolejnych plikach. Do tego zazwyczaj grupuję je w jakichś katalogach i przestrzeniach nazw, aby nie powstał bałagan w projekcie.
  2. A jak próbowałeś i skąd chciałeś się odwoływać? W klasie Form1 czy poza nią? Do których atrybutów?
  3. Obiekty tworzyć się powinno tam, gdzie są potrzebne. Za mało szczegółowe jest Twoje pytanie.
  4. C# nie jest pojebany, tu nie dołącza się plików za pomocą include. Każda klasa w projekcie jest znana kompilatorowi automatycznie. Natomiast w celu ułatwienia sobie pisania kodu, można deklarować użycie przestrzeni nazw przy użyciu using na początku pliku. Dzięki temu nie trzeba używać pełnych nazw typu nazwaprzestrzeni.nazwaprzestrzenizagnieżdżonej.nazwaklasy a jedynie nazwaklasy.
0
somekind napisał(a)
  1. Ja raczej skłaniam się do podejścia jedna klasa w jednym pliku, dlatego dodatkowe klasy dodaję w kolejnych plikach. Do tego zazwyczaj grupuję je w jakichś katalogach i przestrzeniach nazw, aby nie powstał bałagan w projekcie.
  2. A jak próbowałeś i skąd chciałeś się odwoływać? W klasie Form1 czy poza nią? Do których atrybutów?
  3. Obiekty tworzyć się powinno tam, gdzie są potrzebne. Za mało szczegółowe jest Twoje pytanie.
  4. C# nie jest pojebany, tu nie dołącza się plików za pomocą include. Każda klasa w projekcie jest znana kompilatorowi automatycznie. Natomiast w celu ułatwienia sobie pisania kodu, można deklarować użycie przestrzeni nazw przy użyciu using na początku pliku. Dzięki temu nie trzeba używać pełnych nazw typu nazwaprzestrzeni.nazwaprzestrzenizagnieżdżonej.nazwaklasy a jedynie nazwaklasy.

ad1 & ad2. Generalnie to już nie pamiętam, ale ogólnie to nie wychodziło mi połączenie obiektówki z winforms, mam na myśli np. metodę klasy, która operuje na danych w combobox lub innej dowolnej kontrolce. Może w każdym pliku powinienem dodawać jakieś nagłówki, hmm ?

ad3. To znaczy gdzie tak naprawdę ? W aplikacjach pod konsolę tworzyłem obiekty w funkcji Main() i tam się nimi posługiwałem tylko. Kiedy i w jakich przypadkach można tworzyć obiekty korzystając z WinForms ?

ad4. A czy wystarczy dodać plik w Solution Explorer, aby kod z pliku był widoczny w obrębie całego kodu programu + ewentualne using klasa ? Dlaczego grupujesz je w przestrzenie nazw ?

0

Ad 1&2 - jeśli w jakiejś klasie chcesz odwoływać się do np. klasy Combobox, to dodaj na początku pliku using System.Windows.Forms;, to jest przestrzeń nazw z tą klasą.
Tylko uważaj - bo tak naprawdę, to taka potrzeba zachodzi dość rzadko. Jeśli np. masz metodę zwracającą jakiś wynik w zależności od wybranej w Comboboxie pozycji, to nie ma sensu jako argument metody przyjmować całego obiektu Combobox, a jedynie string i przy jej wywoływaniu przekazać Combobox.SelectedText.

Ad 3 - gdybyś podał jakiś konkretny przykład, to może byłoby mi łatwiej odpowiedzieć, bo na razie to pytanie brzmi jak coś w stylu: "kiedy mam iść do sklepu?". Po prostu, gdy potrzebujesz obiektu to go tworzysz. Jedne tworzy się wewnątrz metody, inne jako pola klasy. Wszystko zależy od tego jakie to obiekty, jak długo mają żyć, gdzie i do czego są potrzebne.

Ad 4 - tak, wystarczy dodać w SE. W przestrzenie nazw grupuję, aby mieć porządek. Np. klasy operujące na plikach trzymam w przestrzeni Nazwaprojektu.FileOperations, a wykonujące obliczenia matematyczne w Nazwaprojektu.Calculations. Przestrzeń nazw jest czymś w rodzaju logicznego katalogu, pudełka na klasy. (Nie muszą one odpowiadać strukturze katalogów, chociaż jest to zalecane, żeby łatwiej było się połapać.)

0
somekind napisał(a)

Ad 1&2 - jeśli w jakiejś klasie chcesz odwoływać się do np. klasy Combobox, to dodaj na początku pliku using System.Windows.Forms;, to jest przestrzeń nazw z tą klasą.
Tylko uważaj - bo tak naprawdę, to taka potrzeba zachodzi dość rzadko. Jeśli np. masz metodę zwracającą jakiś wynik w zależności od wybranej w Comboboxie pozycji, to nie ma sensu jako argument metody przyjmować całego obiektu Combobox, a jedynie string i przy jej wywoływaniu przekazać Combobox.SelectedText.

Ad 3 - gdybyś podał jakiś konkretny przykład, to może byłoby mi łatwiej odpowiedzieć, bo na razie to pytanie brzmi jak coś w stylu: "kiedy mam iść do sklepu?". Po prostu, gdy potrzebujesz obiektu to go tworzysz. Jedne tworzy się wewnątrz metody, inne jako pola klasy. Wszystko zależy od tego jakie to obiekty, jak długo mają żyć, gdzie i do czego są potrzebne.

Ad 4 - tak, wystarczy dodać w SE. W przestrzenie nazw grupuję, aby mieć porządek. Np. klasy operujące na plikach trzymam w przestrzeni Nazwaprojektu.FileOperations, a wykonujące obliczenia matematyczne w Nazwaprojektu.Calculations. Przestrzeń nazw jest czymś w rodzaju logicznego katalogu, pudełka na klasy. (Nie muszą one odpowiadać strukturze katalogów, chociaż jest to zalecane, żeby łatwiej było się połapać.)

Trochę jaśniej, jakieś światełko w tunelu, ale to chyba pociąg nadjeżdża! ;)
Z przestrzeniami już rozumiem o co chodzi, ale nadal nie mam pojęcia jak połączyć kontrolki z kodem C# w VS.

Tworząc projekt w VS dla Windows Forms Application mam w SE dwa pliki z kodem źródłowym: Program1.cs oraz Form1.cs. Dotychczas jak pisałem swoje małe programiki to ręcznie przeciągałem kontrolki na formę i kodowałem ich zdarzenia tworząc brzydki i zapewne nie poprawny kod, bo z programowaniem obiektowym to on nie miał chyba nic wspólnego.

Myślę, że zrozumiemy się jak zrobimy mały przykład, a więc następujący problem ja rozwiązałbym w taki sposób:
Mając za zadanie napisać aplikację okienkową z WinForms, która będzie miała na formie: 1 x Button oraz 1 x TextBox, gdzie kliknięcie w button spowoduje wygenerowanie liczby całkowitej int i wyświetlenie jej w textbox'ie ja napisałbym taki kod:

W pliku Program.cs nie zmieniałbym kodu, bo wg. mojej aktualnej wiedzy w połączeniu obiektówki z WinForms nie wiem co miałbym tam wstawić. Dodanie pliku do SE aby utworzyć tam przestrzeń nazw i klasę wydaje mi się aktualnie także bezcelowe, bo nie wiedziałbym jak odwołać się do kontrolek na Form1. ( Z tego co zrozumiałem mogę tworzyć dynamicznie kontrolki na formie dodając using [...].Forms, tak ? )

Wygląd formy: http://img846.imageshack.us/img846/2421/skrin.png

Kod z pliku Form1.cs:

 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Random rnd = new Random();         
            textBox1.Text = rnd.Next().ToString();
        }
    }
}

W jaki sposób można taki prosty programik napisać obiektowo z obsługą WinForms?

Dzięki za pomoc.

0
JerzyKol napisał(a)

W pliku Program.cs nie zmieniałbym kodu, bo wg. mojej aktualnej wiedzy w połączeniu obiektówki z WinForms nie wiem co miałbym tam wstawić.

Tego pliku w większości przypadków nie ma po co ruszać nawet. Tam dzieje się wszystko to co jest potrzebne, czyli uruchomienie głównego okna aplikacji.

Dodanie pliku do SE aby utworzyć tam przestrzeń nazw i klasę wydaje mi się aktualnie także bezcelowe, bo nie wiedziałbym jak odwołać się do kontrolek na Form1.

Nie odwołuj się w nowej klasie do Form1, tylko w Form1 korzystaj z nowej klasy.

Twój przykład jest aż za prosty, ale mogłoby to wyglądać tak, że w SE bierzesz Add -> Class i tworzysz klasę np. RandomOperator:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WindowsFormsApplication1
{
    class RandomOperator
    {
        // aby wiele wywołań Next() pod rząd dało różne wyniki obiekt klasy Random musi być statyczny
        private static Random rand = new Random();  

        public int GetRandomNumber()
        {
            return rand.Next();
        }
    }
}

A kod w Form1 wygląda tak:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private RandomOperator ro = new RandomOperator();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = this.ro.GetRandomNumber().ToString();
        }
    }
}

W tym przypadku to oczywiście przerost formy nad treścią, ale dla kalkulatora miałoby to już większy sens (oddzielna klasa z metodami wykonującymi obliczenia).

( Z tego co zrozumiałem mogę tworzyć dynamicznie kontrolki na formie dodając using [...].Forms, tak ? )

Dynamiczne tworzenie kontrolek (nie w designerze tylko w trakcie działania programu) to inna para kaloszy i może na razie sobie daruj.

Z usingiem chodziło mi np. o coś takiego:

using System.Windows.Forms; //dzięki temu w kodzie poniżej możemy używać ComboBox zamiast System.Windows.Form.ComboBox

namespace WindowsFormsApplication1
{
    class ComboBoxHelper
    {
        public void FillComboWithGender(ComboBox combo)
        {
            combo.Items.Add("Mężczyzna");
            combo.Items.Add("Kobieta");
        }
    }
}

One sprawiają, że łatwiej odwoływać się do klas.

0

Odnosząc się do kodu, który podałeś w Form1:

WOW! Nie wpadłbym NIGDY żeby jako składową deklarować obiekt w innej klasie, bo chyba tak to nazwać można - mam na myśli tworzenie obiektu ro, elegancko to wygląda :)

Tylko tutaj rodzi się moja jedna wątpliwość, bo z tego co zauważyłem to klasę wyprowadzoną z klasy bazowej Form jaką jest Form1 i ewentualnie kolejne utworzone formy należy traktować jako element programu, który służy TYLKO do wyświetlania i zarządzania kontrolkami poprzez wywoływanie odpowiednich metod/składowych z utworzonych obiektów klas, gdzie obiekty te są tworzone w składowych klasy odpowiedniej formy, dobrze rozumuję w tej kwestii ?

Bardzo Ci dziękuje za pomoc, bardzo ładnie mi to wytłumaczyłeś!

0

Obiekt ro to po prostu pole klasy Form1. Tak jak polami tej klasy są kontrolki textBox1 czy też button1.

I masz rację, formy to tylko interfejs użytkownika, powinny służyć tylko do wyświetlania informacji i pobierania poleceń od użytkownika. Wszelkie obliczenia, operacje plikowe, działania na bazach danych powinny być wykonywane w oddzielnych klasach i metodach wywoływanych jednie z interfejsu na żądanie.

0
somekind napisał(a)

Obiekt ro to po prostu pole klasy Form1. Tak jak polami tej klasy są kontrolki textBox1 czy też button1.

I masz rację, formy to tylko interfejs użytkownika, powinny służyć tylko do wyświetlania informacji i pobierania poleceń od użytkownika. Wszelkie obliczenia, operacje plikowe, działania na bazach danych powinny być wykonywane w oddzielnych klasach i metodach wywoływanych jednie z interfejsu na żądanie.

Chyba już wszystko jasne. Pozostało mi to poćwiczyć. Dzięki.

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