» »

C# - runtime generiranje in klicanje kontrol

C# - runtime generiranje in klicanje kontrol

stalker ::

VS 2015, winform C#, hobi programer.

Uporabnik generira določeno število miz, vsaka miza pa vsebuje 3 kontrole: 2x label in 1x checkbox. Na vseh mizah in kontrolah se izvajajo iste funkcije, vendar vsaka miza deluje za sebe.
V
public Form1()
generiram kontrole (plus ostala solata):
Label miza = new Label();
miza.Name = "miza_" + i.ToString();

CheckBox chk_start = new CheckBox();
chk_start.Name = "chk_start_" + i.ToString();

Label stoparica = new Label();
stoparica.Name = "stoparica_" + i.ToString();

Potem s to kodo kličem funkcijo:
chk_start.CheckedChanged += new EventHandler(chk_start_click);

In v tej funkciji:
void chk_start_click(object sender, EventArgs e)
        {       
            CheckBox chek = (sender as CheckBox);
            if (chek.Checked == true)
            {
               chek.BackColor = Color.Lime;
               miza_17.BackColor = Color.Lime;
               stoparica_17.BackColor = Color.Lime;

               ...itd...

hočem, da ob čekiranju recimo chk_start_17 hkrati operiram tudi z miza_17 (label) in stoparica_17 (label). Kako to najbolj učinkovito dosežem?

PS: Imam polno različnih funkcij in pri vseh operiram s tremi kontrolami hkrati. Zadovoljen bom tudi, če mi priporočate kakšen drugačen pristop.
  • spremenilo: stalker ()

kuall ::

globalne spremenljivke

stalker ::

@kuall: s tvojim odgovorom mi nisi pomagal nič.

Dodatek: Najbolj me zanima, kako v funkciji izvem, katera kontrola je bila poklikana in kako kličem ostale kontrole z isto zaporedno številko?

frudi ::

Nekaj v tem stilu - najprej iz imena kontrole, ki je sprožila akcijo, pridobiš ID (recimo 17), nato pa s tem ID-jem sestaviš imeni ostalih label:
var chek = sender as CheckBox;
var id = chek.Name.Replace("chk_start_", "") as Label;
var table = this.Controls.Find("miza_" + id) as Label;
var stopwatch = this.Controls.Find("stoparica_" + id);

table.BackColor = ... 

Kjer je 'this' kontejner, znotraj katerega se nahajajo kontrole. Tipično je to kar forma, na kateri se nahajaš.
1ACDoHVj3wn7N4EMpGVU4YGLR9HTfkNhTd... in case I've written something useful :)

windigo ::

Containment. Naredi UserControl Miza, ki vsebuje labele, checkbox, štoparico in vse event handlerje.
Miza miza1 = new Miza(1);
Miza miza2 = new Miza(2);
...


Pri čemer se znebiš čuda enega kastanja in ugotavljanja, od kod je priletelo.

Koda tukaj je pisana na pamet za ilustracijo. V resnici ti bo že sam designer v code behindu poimenoval in inicializiral vse kontrole na formi, ti jih rabiš samo še zvezati na event handlerje.
public class Miza : UserControl
{
    int _id;
    Label _naziv;
    Label _stoparca;
    CheckBox _knof;

    public Miza(int id)
    {
        _id = id;
        _naziv = new Label();
        _naziv.Name = "miza_" + _id.ToString();

        _knof = new CheckBox();
        _knof.Name = "knof_" + _id.ToString();

        _stoparca = new Label();
        _stoparca.Name = "stoparca_" + id.ToString();

        _knof.CheckedChanged += new EventHandler(PritiskNaKnofek);
    }

    void PritiskNaKnofek(object sender, EventArgs e)
    {
        if (_knof.Checked)
        {
            _knof.BackColor = Color.Lime; // great taste
            _stoparca.BackColor = Color.Lime; // yeah!
            ...
        }
    }    
}

RedDrake ::

Predlog.
Naredi tri globalne Dictionary-e <int,Label> (kot primer), pa vsaki kontroli določi tag polje.
To tag polje se mi zdi pride v sender objektu pri eventu, kar odpravi castanje. (Tole je iz spomina, nisem pisal winform programa že vsaj 5 let, lahko da je potreben cast!). V tem tagu shraniš id, ki je hkrati int ključ v dictionary-u.
Id prebereš v eventu, potem pa samo kličeš mize[id].BackColor = ...
Lahko narediš tudi containment, in narediš tako, kot je predlagal bpbpbp, a rabiš vseeno en <int,UserControl> dictionary za mize.
Če želiš lahko vržem tudi v kodo kot primer.

LP

Zgodovina sprememb…

  • spremenil: RedDrake ()

stalker ::

Hvala za predloge! Bom poizkusil najprej frudijevo varianto in potem ostale.
@RedDrake: Ni treba kode, razumem postopek, ki si ga predlagal.

Zgodovina sprememb…

  • spremenilo: stalker ()

stalker ::

frudi je izjavil:

Nekaj v tem stilu - najprej iz imena kontrole, ki je sprožila akcijo, pridobiš ID (recimo 17), nato pa s tem ID-jem sestaviš imeni ostalih label:

var chek = sender as CheckBox;
var id = chek.Name.Replace("chk_start_", "") as Label;
var table = this.Controls.Find("miza_" + id) as Label;
var stopwatch = this.Controls.Find("stoparica_" + id);

table.BackColor = ...

Kjer je 'this' kontejner, znotraj katerega se nahajajo kontrole. Tipično je to kar forma, na kateri se nahajaš.

Uporabil sem tvojo rešitev, ampak malo dodelano, ker kontrole ustvarjam v Form1, kličem jih pa iz funkcije.
private void chk_start_click(object sender, EventArgs e)
        {
            var chek = sender as CheckBox;
            var id = chek.Name.Replace("chk_start_", "");            
            var table = Controls.Find("miza_" + id, true).FirstOrDefault();
            var stopwatch = Controls.Find("stoparica_" + id, true).FirstOrDefault();

            if (chek.Checked == true)
            {
            ...itd...


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

ASP.NET, C# spletna aplikacija in dodajanje kontrol v run time-u programa

Oddelek: Programiranje
7940 (672) kuall
»

[c#] ukaz radirka

Oddelek: Programiranje
91029 (822) japol
»

[c#] picturebox, slika na sliko

Oddelek: Programiranje
151002 (812) japol
»

[VC++, MFC] OnPaint

Oddelek: Programiranje
5889 (856) whatever
»

visual basic 2008 express edition

Oddelek: Programiranje
221725 (1152) sel

Več podobnih tem