Autor Téma: Změny ve formuláři  (Přečteno 2555 krát)

Offline Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 228
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Změny ve formuláři
« kdy: 13-04-2014, 12:12:03 »
Dobrý den,
mám formulář v něm nějaká Tcomba a TEdity. Do nich na načtu z recordu hodnoty. Ty pak můžu nebo nemusím nějak editovat.
Pak se přesouvám na jiný record, ale chci pohlídat, jestli jsem udělal ve formuláři změny a optat se před přesunutím, jestli je mám uložit.
Pokud změny nebyly, neptám se na nic a načtu nový record do formuláře.
Vždycky jsem to dělal "pěšky", že jsem položku po položce kontroloval, ale nejde to udělat nějak hromadně?
Třeba nějaký hromadný OnEnter?

Dík - Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline Daniel_Andrascik

  • Guru
  • *****
  • Příspěvků: 503
  • Karma: 20
    • Verze Delphi: D2007, D10.4
Re:Změny ve formuláři
« Odpověď #1 kdy: 13-04-2014, 13:07:21 »
som zvedavy na navrhy, ale ja to vidim tak ze istota je gulomet, takze radsej polozku po polozke. Ked pouzivas viacero druhov komponent a pripadne este od tretich stran tak by som z pohladu datovej bezpecnosti ruku do ohna za udalosti typu onenter, onleave, onchange atd nedal.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1559
  • Karma: 37
    • Pepak.net
Re:Změny ve formuláři
« Odpověď #2 kdy: 13-04-2014, 13:23:36 »
Obecně se to moc udělat nedá, protože v podstatě není žádná událost nebo příznak, která by řekla, "ano, skutečně došlo ke změně". Dalo by se to řešit tak, že pro všechny komponenty použiješ nějaké svoje verze, které takovou property budou mít, ale je dost pracné to takhle připravit.

Relativně jednoduchá a schůdná (nicméně ne vždy výhodná) cesta by byla, použít DB-aware komponenty (respektive Live Binding v novějších Delphi) a navázat je na nějakou TMemoryTable, která bude mít jeden řádek, na začátku naplněný na vstupní hodnoty. Potom se vždycky můžeš podívat, jestli je State=dsEdit (a tedy aspoň na jedné komponentě proběhl pokus o změnu dat) nebo ne.

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Změny ve formuláři
« Odpověď #3 kdy: 13-04-2014, 14:41:02 »
pepaku, není to trochu overkill?

Já to řeším jednou TNotifyEvent (typicky OnChange) pro všechny zúčastněné komponenty. Když se zavolá, tak změním status tlačítka uložit (zčervenám ho), aby i uživatel poznal, že něco změnil. Při skoku na jiný řádek zkontroluju status tlačítka a zeptám se uživatele, jestli chce změny uložit.

Důležité je po načtení dat status tlačítka vždy vynulovat, protože OnChange se u nějakých komponent spustí.

Funguje 100% jistě a je to strašně jednoduché.

PS: abych předešel ostatním diskuzím. OnChange neřekne "ano, skutečně došlo ke změně", ale řekne "mohlo dojít ke změně", což je z mého pohledu dostačující - fungují tak všechny programy včetně např. editoru Delphi.
« Poslední změna: 13-04-2014, 14:47:24 od oxo »
Embarcadero Technology Partner

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1559
  • Karma: 37
    • Pepak.net
Re:Změny ve formuláři
« Odpověď #4 kdy: 13-04-2014, 15:40:49 »
pepaku, není to trochu overkill?
Je, ale funguje to relativně bezpracně i se standardními komponentami.

Citace
Já to řeším jednou TNotifyEvent (typicky OnChange) pro všechny zúčastněné komponenty. Když se zavolá, tak změním status tlačítka uložit (zčervenám ho), aby i uživatel poznal, že něco změnil. Při skoku na jiný řádek zkontroluju status tlačítka a zeptám se uživatele, jestli chce změny uložit.
Pokud ti OnChange zachytí požadované změny a pokud ji nepotřebuješ využívat i jinde, tak snad ano. Mě se nikdy nepodařilo splnit obě podmínky.

Offline Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 228
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Změny ve formuláři
« Odpověď #5 kdy: 14-04-2014, 07:53:01 »
Jedná se vlastně o změny v textboxech nebo v combech, takže všechno komponenty s vlastností .TEXT. Napadlo mě po načtení původního rekordu obsah všech textů sloučit do "Megastringu" (on zas tak Mega nebude) a pak při požadavku přejít na další rekord to zopakovat do jiného megastringu a oba dva prostě porovnat. DB komponenty nechci zavádět, databáze přicházejí a odcházejí, File of record, nebo File of text jsou věčné.

Dalik.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 228
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Změny ve formuláři
« Odpověď #6 kdy: 14-04-2014, 08:37:00 »
Citace
Já to řeším jednou TNotifyEvent (typicky OnChange) pro všechny zúčastněné komponenty
Nějaký příkládek by nebyl?
Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3342
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Změny ve formuláři
« Odpověď #7 kdy: 14-04-2014, 08:40:01 »
Jedná se vlastně o změny v textboxech nebo v combech, takže všechno komponenty s vlastností .TEXT. Napadlo mě po načtení původního rekordu obsah všech textů sloučit do "Megastringu" (on zas tak Mega nebude) a pak při požadavku přejít na další rekord to zopakovat do jiného megastringu a oba dva prostě porovnat. DB komponenty nechci zavádět, databáze přicházejí a odcházejí, File of record, nebo File of text jsou věčné.
Reseni s "megastringem" je mozne, ale je spis z kategorie Quick&Dirty, nez reseni na vecne casy ;-)

Po nas zakaznici chteli, aby u slozitejsich dialogu bylo videt, ktere widgety byly zmeneny a aby slo o skutecnou zmenu, (tj. napr. kdyz mam v editu text Gogo a rucne napisu Gogo, tak to nebude modified), ktere maji neplatnou hodnotu apod.

V jedne rodine produktu, ktera pouzivala vlastni ORM, jsme meli u kazdeho "pole" vlastnost modified, u jine rodiny produktu mame vlastni VCL komponenty, kde vlastnost modified ma kazdy GUI widget... V obou pripadech si to pamatuje originalni hodnotu a pri dotazu na modified to zjistuje rozdil.

Kdybych mel delat nejake dalsi reseni mimo DB awared widgety, tak bych dneska nejspis pridal dalsi record pro puvodni hodnoty, oba recordy zaboxoval do nejake tridy, jejiz properties bych pouzival pro live binding a tu tridu udelal tak, aby byla obecna a umela pracovat s ruznymi recordy a podporvala kontrolu modified + validaci aj.

Ale protoze nemam prilis velke pochopeni pro reinkarnaci recordu, tak bych nakonec nejspis vubec zadny record nepouzil a nacpal je do nejake iterovatelne struktury podobne jako jsou TFields, cili bych vlastne jen modernizoval nase puvodni reseni s ORM pro live bindings...


Offline TLama

  • Guru
  • *****
  • Příspěvků: 597
  • Karma: 31
    • Verze Delphi: 7, 2009, XE3
Re:Změny ve formuláři
« Odpověď #8 kdy: 14-04-2014, 08:45:30 »
Napadlo mě po načtení původního rekordu obsah všech textů sloučit do "Megastringu" (on zas tak Mega nebude) a pak při požadavku přejít na další rekord to zopakovat do jiného megastringu a oba dva prostě porovnat.

To bych nedělal:

1. pole     2. pole
'12345'     '6'
'1'             '23456'

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3342
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Změny ve formuláři
« Odpověď #9 kdy: 14-04-2014, 08:52:12 »
To bych nedělal:
No musel by sis mezi ne dat nejaky oddelovac, ale pak je otazka, proc to vubec delat a proc je treba nenasackovat do TDictionary<string, string>

Offline TLama

  • Guru
  • *****
  • Příspěvků: 597
  • Karma: 31
    • Verze Delphi: 7, 2009, XE3
Re:Změny ve formuláři
« Odpověď #10 kdy: 14-04-2014, 10:24:15 »
To bych nedělal:
No musel by sis mezi ne dat nejaky oddelovac, ale pak je otazka, proc to vubec delat a proc je treba nenasackovat do TDictionary<string, string>

Jistě. On jen ten popis sloučit do "Megastringu" zaváněl sloučením bez oddělovače. A ano, pro uložení původních hodnot jednotlivých komponent by
TDictionary<TComponentName, string>, případně těžkopádnější TDictionary<TComponentName, Variant> nebyly od věci.
« Poslední změna: 14-04-2014, 10:34:36 od TLama »

Offline Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 228
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Změny ve formuláři
« Odpověď #11 kdy: 14-04-2014, 14:05:06 »
TDictionary jsem v helpu nenašel, ale rád se poučím. Udělal jsem to takhle (zřetězení). Porovnání je pak už snadné.
Kód: Delphi [Vybrat]
  1. procedure TForm17.Button1Click(Sender: TObject);
  2. var ret2: string;
  3.     i: integer;
  4. begin
  5. for i:=0 to form17.ControlCount - 1 do
  6.   if form17.components[i] is TEdit then ret2:=ret2 + TEdit(components[i]).text + ';';
  7.   Label1.caption:=ret2;
  8. end;
  9.  
Oddělovač jsem tam dal středník, ten pak nemůžu použít na konci jedné a začátku následující položky. Ale to je krajně nepravděpodobné.

Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline Faltynek

  • Plnoletý
  • ***
  • Příspěvků: 228
  • Karma: 2
    • Verze Delphi: D5 Enterprise, D2009
Re:Změny ve formuláři
« Odpověď #12 kdy: 14-04-2014, 14:21:16 »
Ještě chybička, do cyklu patří ComponentCount a ne ControlCount.
Dalibor.
Dalibor (D2009 Enterprise, dřív D5Enterprise)

Offline Ondřej Pokorný

  • Guru
  • *****
  • Příspěvků: 815
  • Karma: 59
    • Verze Delphi: Primárně Lazarus, jinak D7 až aktuální
    • Kluug.net
Re:Změny ve formuláři
« Odpověď #13 kdy: 14-04-2014, 14:28:40 »
Já osobně bych si zinicializoval Ret2 (např. na prázdný string), než bych z ní četl.

Pardon, má chyba, lokální stringy jsou automaticky inicializovány na ''. Takže vše v pořádku.
« Poslední změna: 14-04-2014, 14:42:55 od oxo »
Embarcadero Technology Partner

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3004
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Změny ve formuláři
« Odpověď #14 kdy: 14-04-2014, 14:55:25 »
Já osobně bych si zinicializoval Ret2 (např. na prázdný string), než bych z ní četl.

Pardon, má chyba, lokální stringy jsou automaticky inicializovány na ''. Takže vše v pořádku.

No já bych ho inicializoval, protoze jsem se uz napalil v případe, že jsem jako "scitaci" string pouzil navratovou hodnotu funkce. Pro neznale: navratova hodnota funkce je predavana jakoby var parametr tj. muze uz neco obsahovat. A to jsou pak chyby...
Embarcadero MVP - Czech republic