Diskuze: Procházení textboxu z formuláře

C# .NET .NET (C# a Visual Basic) Procházení textboxu z formuláře American English version English version

Avatar
tomas
Člen
Avatar
tomas:

Ahoj všem. Mám problém s načtení textboxů z formuláře. Mám následující kód.

private void tlZapsatZmeny_Click(object sender, EventArgs e)
{

    foreach (Control c in controls)
    {

        if (c.GetType() is TextBox)
        {
            ......
        }
    }
}

Potřebuju zjistit obsah všech textboxů z formuláře. Problém je v tom, že mám ve formuláři splitContainer a tento kód mě vrací pouze jeden control prvek a tím je právě ten splitcontainer.

 
Odpovědět 11.6.2013 17:34
Avatar
hanse
Člen
Avatar
hanse:

v texBoxu je text - string, takže můžeš napsat třeba:

string s = texBox1.Text

a následne s obsahem každého textboxu pracovat jako se stringem (např. zkoušet parsovat a zjistit, jestli se nejedná o číslo, atd.)

 
Nahoru Odpovědět 11.6.2013 17:49
Avatar
hanse
Člen
Avatar
Odpovídá na tomas
hanse:

Aha, už sem asi pochopil tvůj problém:

foreach (Control c in controls)
{

    if (c is TextBox)
    {

        string s = c.Text;
        listString.Add(c.Text);
    }
}
 
Nahoru Odpovědět 11.6.2013 18:18
Avatar
tomas
Člen
Avatar
Odpovídá na hanse
tomas:

No nepochopil :), můj problem je v tom, že cyklus foreach (Control c in controls) projde jenom jednou. Protože v controls je jenom jeden objekt, a to je System.Window­s.Forms.Split­Container. A tento objekt má dva kontejnery. Jeden obsahuje datagrid a druhy obsahuje TabControl s dvěma záložkami. Na jedné z nich je 7 TextBoxů, 2 tlačítka, 2 chackBoxy a 7 labelů. Tudíš ta podmínka nikdy nebude splněna. Přímej přístup k tomu textboxu mám. TextBox1.text mě funguje. Ale já obsah porovnávám s původní hodnotou a posílám do DB. Lze to pro každé pole udělat sólo, ale já chci v tom cyklu projít všechny pole a udělat na nich stejné operace. Jen nevím jak se k tomu TexBoxu v tom cyklu dostat.

 
Nahoru Odpovědět 11.6.2013 19:52
Avatar
hanse
Člen
Avatar
Odpovídá na tomas
hanse:

Hm... ono taky dost záleží na tom, jak/kde máš definované controls (+ jsi si jistý, že controls obsahuje System.Window­s.Forms.Split­Container a ne např. splitcontainer1? Kdybys definoval controls jako List<Control> a přidal do něj všechny prvky (např. textBox1, textBox2, splitContainer1­...), tak ti kód bude běhat, jak má.

 
Nahoru Odpovědět 11.6.2013 20:19
Avatar
Odpovídá na tomas
Luboš Běhounek (Satik):

Budeš muset asi projet všechny controly rekurzivně.

Třeba nějak takhle (psáno od oka, nezkoušel jsem to):

Stack<Control> stack = new Stack();
List<TextBox> textboxy = new List<TextBox>();

foreach (Control c in this.Controls)
    stack.Push(c);

while (stack.Count>0)
{
    Control c = stack.Pop();
    if (c is TextBox)
    {
        textboxy.Add(c);
    }

    foreach (Control c2 in c.Controls)
        stack.Push(c2);
}
Nahoru Odpovědět 11.6.2013 20:32
:)
Avatar
tomas
Člen
Avatar
Odpovídá na hanse
tomas:

No abych pravdu řekl, tak jsem tento způsob načtení našel v knížce. Textbox jsem definoval v design režimu ve visualstudiu. A jsem si jistý, že to vrátí SplitContainer. Všechny prvky(label, texbox, button, ..) jsou definovaný v privátní metodě InitializeCom­ponent(). Jako příklad uvedu jeden textbox.

this.poleJmeno = new System.Windows.Forms.TextBox();

A potom metoda obsahuje i přidání jednotlivých prvků do controls.

this.grpZmenaUzivatele.Controls.Add(this.lblJmeno);

Jakže předpokládám, že jsou všechny prvky v controls obsaženy.

 
Nahoru Odpovědět 12.6.2013 11:20
Avatar
tomas
Člen
Avatar
Odpovídá na tomas
tomas:

už jsem na to asi přišel. Mám celej formulář obalený v groupBoxu a on mě přidává všechny prvky do controls toho groupBoxu, když jsem ten grbzmenaUzivatele odmázl, měl jsem ten prvek již dostupný. Jdu to ještě o testovat.

 
Nahoru Odpovědět 12.6.2013 11:26
Avatar
hanse
Člen
Avatar
Odpovídá na tomas
hanse:

že ty prvky jsou definovaný v InitializeCom­ponent() vim - dej si ve VS Go To Definition poleJmeno... :)

Je rozdíl, jestli napíšeš Controls (kolekce control prvků) a controls (to co si sám nadefinuješ, například i jako kolekce List<Control>, případně jinak - pokud to má pro tebe smysl).

Doporučuju zkusit pro různé prvky (s patričnou úpravou):

foreach (Control c in this.Controls)
{
    if (c == this.textBox1)
        MessageBox.Show("Jsem textBox1!", "zprava",MessageBoxButtons.OK);
}
 
Nahoru Odpovědět 12.6.2013 13:37
Avatar
Odpovídá na hanse
Luboš Běhounek (Satik):

To dělá ten můj kód výše, projede všechny controly na formu a všechny controly těch controlů a všechny controly controlů těch controlů... :)

A textboxy uloží do listu

Nahoru Odpovědět 12.6.2013 13:43
:)
Avatar
hanse
Člen
Avatar
Odpovídá na Luboš Běhounek (Satik)
hanse:

To ano, já ale narážel na něco jiného :`

 
Nahoru Odpovědět 12.6.2013 14:00
Avatar
tomas
Člen
Avatar
Odpovídá na hanse
tomas:

Ten tvůj kód mě nepomůže. A v mém případě je nesmyslný. Je nesmysl porovnavat promenou s konkrétním textboxem. Já se k tomu textboxu dostanu přímo takle.

string obsahPole = poleJmeno.ToString();

Tvoje podmínka je proto nesmyslná, a nebude nikdy pravda, protože cyklus projde jenom jednou s následujícím výsledkem

c = System.Windows.Forms.SplitContainer

Chápeš? No vyřešil jsem to úpravou souboru .desinger.cs. Není to ale korektní řešení, protože jak udělám jakoukoliv změnu ve vizuání části, tak se mě to pole smaže.

private System.Collections.Generic.List<System.Windows.Forms.TextBox> seznamTextBox;

seznamTextBox = new System.Collections.Generic.List<System.Windows.Forms.TextBox>();
this.seznamTextBox.Add(this.poleJmeno);
this.seznamTextBox.Add(this.polePrijmeni);

No a teď už mám všechny pole v jediným seznamu.

foreach (Control c in seznamTextBox)
{
   // pri prvnim pruchodu obsahuje promena c první objekt textbox poleJmeno
   string sloupec = c.Tag.ToString();
   string hodnota = c.Text.ToString();
   metodaUlozDoDB(sloupec, hodnota, puvodniHodnota);
}

Rozumíme si? Co potřebuju? Nevím jestli to dobře vysvětluju.

 
Nahoru Odpovědět 12.6.2013 15:23
Avatar
tomas
Člen
Avatar
tomas:

Teď koukám že to pole můžu definovat i jinde, nemusí to být v tom desinger.cs. Ale pořád je to pole které musím vytvořit. Myslel jsem si, že můžu načíst ty textboxy přímo, bez ukládání do nějakého pole. Ale tak jak jsem to myslel to asi nejde. Takže abych toho docílil, tak prostě musím znát název toho textBoxu. Prostě nejde vybrat všechny prvky na formuláři a projít si je s podmínkou, že jestli je prvek textbox, udělej akci.

 
Nahoru Odpovědět 12.6.2013 15:30
Avatar
Odpovídá na tomas
Luboš Běhounek (Satik):

Nečetl jsi můj příspěvek? :)
Ten kód proleze všechny Controly na formu a do listu ti vybere jen textboxy, takže pak už jen proiteruješ výsledné textboxy.

Editováno 12.6.2013 15:36
Nahoru Odpovědět 12.6.2013 15:35
:)
Avatar
tomas
Člen
Avatar
tomas:

Ha, tak jsem na to přišel. Jsem idiot, byla to blbost. Všem se omlouvám, ale mějte se mnou slitování, teprve do tajů c-sharpu pronikám. následující kód mě funguje tak jak má. Já psal podmínku pro cyklus špatně. Popel na moji hlavu.

foreach (Control c in grpZmenaUzivatele.Controls)
{
    if (c is TextBox)
    {
        string sloupec = c.Tag.ToString();
        string hodnota = c.Text.ToString();

    }
}

Jinak děkuju za snahu, vážím si jí. Díky!

Editováno 12.6.2013 15:42
 
Nahoru Odpovědět 12.6.2013 15:42
Avatar
tomas
Člen
Avatar
Odpovídá na Luboš Běhounek (Satik)
tomas:

Díval a neproleze :), this.Controls vrací jen ten SplitContainer. Řešení jsem už napsal. Asi mu vadí, že mám textboxy uvnitř jiného prvku.

 
Nahoru Odpovědět 12.6.2013 15:45
Avatar
Domiy
Neregistrovaný
Avatar
Odpovídá na tomas
Domiy:

Proboha! typeof ti nic neříká?

 
Nahoru Odpovědět 12.6.2013 15:58
Avatar
Odpovídá na tomas
Luboš Běhounek (Satik):

Ale nezkoušel jsi to, jen sis řekl, že to nebude fungovat :)
SplitContainer je totiž potomek Controlu, takže by to fungovalo ;)

Nahoru Odpovědět 12.6.2013 16:01
:)
Avatar
hanse
Člen
Avatar
Odpovídá na tomas
hanse:
string obsahPole = poleJmeno.ToString();
  • takto nezjistíš obsah pole/prvku, ale Třídu prvku.

Udělej si nový formulář, kde si uděláš textBox1 a zkus ten code.
(mimochodem c.Text je dycky string, takže to ToString() tam nemusí být).

Hlavně, že ti to už chodí :)

 
Nahoru Odpovědět  +1 12.6.2013 16:08
Avatar
tomas
Člen
Avatar
Odpovídá na Luboš Běhounek (Satik)
tomas:

Ale já to zkousel, jenže jsem narazil na stejnej problém. Ten cyklus prošel jen jednou a vrátil ten kontejner. Ale je fakt, že jsem zkusil jen ten cyklus a když jsem viděl že to vrací jen ten kontejner, tak jsem to dál neřešil. Teď ale koukám, že tam máš další cyklus kterej ten kontejner prochází, takže by to asi taky fungovalo.

 
Nahoru Odpovědět 12.6.2013 16:28
Avatar
tomas
Člen
Avatar
Odpovídá na Domiy
tomas:

Nechápu jak to myslíš. V čem je rozdíl mezi typeof a is? Doberu se ke stejnému výsledku.

 
Nahoru Odpovědět 12.6.2013 16:29
Avatar
Kit
Redaktor
Avatar
Odpovídá na tomas
Kit:

Ne tak docela. Tohle mi našel Google:

if (obj is ClassA) {}
if (obj.GetType() == typeof(ClassA)) {}

is tells you if the object implements ClassA anywhere in its type heirarchy. GetType() tells you about the most-derived type.

Jinými slovy: is proleze celý strom dědičnosti. Pokud nalezne shodu, dá výsledek true. typeof() jen poskytne název třídy. Každý zápis je tedy vhodný k jinému účelu.

Nahoru Odpovědět  +1 12.6.2013 16:38
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
tomas
Člen
Avatar
Odpovídá na Kit
tomas:

Aha, tak je mě to jasný. Dík.

 
Nahoru Odpovědět 12.6.2013 16:46
Avatar
Odpovídá na tomas
Luboš Běhounek (Satik):

Teď koukám, že ten můj kód by byl zbytečně složitý, nevšiml jsem si, že Form také dědí od Control :)

Stack<Control> stack = new Stack();
List<TextBox> textboxy = new List<TextBox>();

stack.Push(this);

while (stack.Count>0)
{
    Control c = stack.Pop();
    if (c is TextBox)
    {
        textboxy.Add(c);
    }

    foreach (Control c2 in c.Controls)
        stack.Push(c2);
}
Nahoru Odpovědět 12.6.2013 17:04
:)
Avatar
Jan Vargovský
Redaktor
Avatar
Jan Vargovský:

Nějak moc jsem to tu nečetl, ale jestli chceš proiterovat všechny prvky v tom containeru, tak ten se skládá z jednotlivých panelu a ten panel už tam potom obsahuje ty controls. takže na příkladu takto:

foreach (Control c in splitContainer1.Panel1.Controls)
            {
                if (c is Label)
                    MessageBox.Show(c.Text);
            }

Zkusím ještě prozkoumat jestli by nešlo proiterovat ty panely v containeru a pak v nich iterovat ty controly

 
Nahoru Odpovědět 12.6.2013 17:44
Avatar
Jan Vargovský
Redaktor
Avatar
Jan Vargovský:

Tak jsem se na ten control blíž podíval a je tam fixla velikost na 2 panely, takže jestli to máš narvané v obou, tak musíš proiterovat obadva pod sebou(první ten Panel1 a pak Panel2) - snad je to to, na co ses ptal :)

 
Nahoru Odpovědět 12.6.2013 17:49
Avatar
tomas
Člen
Avatar
Odpovídá na Jan Vargovský
tomas:

ne mam to jen v jednom, v tom druhem je jen datagrid

 
Nahoru Odpovědět 12.6.2013 20:37
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na tomas
Jan Vargovský:

No, toje fuk... A je to to, co jsi myslel?

 
Nahoru Odpovědět 12.6.2013 22:50
Avatar
tomas
Člen
Avatar
Odpovídá na Jan Vargovský
tomas:

jo je to ono, kousek víš už jsem to podobně vyřešil. diky

 
Nahoru Odpovědět 12.6.2013 23:13
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 29 zpráv z 29.