Diskuze: Procházení textboxu z formuláře
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 29 zpráv z 29.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
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.)
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);
}
}
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.Windows.Forms.SplitContainer. 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.
Hm... ono taky dost záleží na tom, jak/kde máš definované controls (+ jsi si jistý, že controls obsahuje System.Windows.Forms.SplitContainer 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á.
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);
}
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ě InitializeComponent(). 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.
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.
že ty prvky jsou definovaný v InitializeComponent() 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);
}
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
To ano, já ale narážel na něco jiného
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.
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.
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.
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!
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.
Ale nezkoušel jsi to, jen sis řekl, že to nebude fungovat
SplitContainer je totiž potomek Controlu, takže by to fungovalo
string obsahPole = poleJmeno.ToString();
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í
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.
Nechápu jak to myslíš. V čem je rozdíl mezi typeof a is? Doberu se ke stejnému výsledku.
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.
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);
}
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
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
ne mam to jen v jednom, v tom druhem je jen datagrid
jo je to ono, kousek víš už jsem to podobně vyřešil. diky
Zobrazeno 29 zpráv z 29.