Python týden Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Pouze tento sleva až 80% na kurzy Python
Avatar
Michaal.K
Člen
Avatar
Michaal.K:29. dubna 14:40

Ahoj,
potřeboval bych behěm prohledávání dataGridView deaktivovat všechny komponenty na formuláři a jejich události a až skonči vyhledávání tak je zpět aktivuji.
Na formu mám dataGridView a několik tlačítek. Když začnu foreach cyklem prohledávat dataGridView tak to chvíli trvá a já bych chtěl během toho hledání zneaktivnit tlačítka (aby na ně uživatel nemohl kliknout). Pokud jsem to udělal prostým btn.enable = false tak jsou tlačítka zašednutá. Pokud na ně přesto kliknu i když je tlačítko zašedlé tak se nic nestane. To je správně. Jakmile ale dokončím vyhledávání a zaktivním tlačítko (btn.enable = true) tak se vyvolá událost z předchozího kliknutí aniž bych na něj klikl a to je ten problém tuto událost potřebuji potlačit.

Zkusil jsem: btn.enable = false;

Chci docílit: Potřeboval bych během vyhledávání zneaktivovat komponenty a vypnout i jejich události.

Díky moc za pomoc....

 
Odpovědět 29. dubna 14:40
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:29. dubna 18:36
 btn.Enabled = false;
 ProvadejHledani();
 Application.DoEvents(); //tady se provedou nesplněné úlohy (např. kliknutí na neaktivní tlačítko)
//a až pak aktivuj tlačítko
 btn.Enabled = true;
Editováno 29. dubna 18:38
 
Nahoru Odpovědět 29. dubna 18:36
Avatar
JerryM
Člen
Avatar
JerryM:30. dubna 7:22

pokud knikneš na tlačítko co je Enabled = false tak se událost do tlačítka nedostane. Je divný jestli ano. To je chyba. Pod jakým .NET děláš ? zkusil si 4.7.2 ??? jinak mužeš zkusit dát Visible = false na nadřazenou komponentu tedy asi .. Panel ? Máš to na panelu že ? ty všechny tvoje komponenty včetně toho datagridview ?

 
Nahoru Odpovědět  -1 30. dubna 7:22
Avatar
Michaal.K
Člen
Avatar
Odpovídá na JerryM
Michaal.K:30. dubna 8:49

Ahoj, dokud je tlačítko enabled = false a já na něj kliknu tak se událost nespustí. Ale když dám tlačítko enabled = true a předtím jsem na něj kliknul tak se událost spustí. Používám .NET 4.5.2.
Tlačítka mám na panelu ale dataGridView ne. Pokud dám panelu visible = false viz. kod níže

panel.Visible = false;
Vyhledani();
panel.Visible = true;

Tak se tlačítka během vyhledávání ztratí a když je vyhledávání dokončeno tak se objeví...
Ale to nechci aby tam tlačítka takto mizely a objevovaly se....

 
Nahoru Odpovědět 30. dubna 8:49
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:30. dubna 8:55

Děkuji za radu. Pokud přidám do kódu:

Application.Do­Events();

Tak to již funguje. Chtěl jsem se zeptat proč se událost na tlačítku spustí, když na něj bylo kliknuto během jeho neaktivního stavu? Tlačítko si tedy musí pamatovat, že během enable = false bylo stisknuto?

 
Nahoru Odpovědět 30. dubna 8:55
Avatar
JerryM
Člen
Avatar
JerryM:30. dubna 9:00

když klikneš na tlačítko, které už je Enabled = false tak se událost nevyvolá
pokud ano je něco špatně a máš špatně časování. ono totiž chvíli trvá než se Enabled = false provede... víš ... jinak je dobré si to ošetřit v metodě buttonXX_Click jestli si tam už jedno byl nebo ne nějakou globální proměnnou ..

 
Nahoru Odpovědět  -3 30. dubna 9:00
Avatar
JerryM
Člen
Avatar
JerryM:30. dubna 9:04

aby sma oba mlivili o tom samém .. když je tlačítko Enabled = false a ty na něj klikneš a pak třeba za 1 sec dáš Enabled = true tak se to kliknutí starý 1 sec nikde nepamatuje .. pokud se událost vyvolá máš něco špatně ...děláš něco špatně .. jestli si Event od tlačítka zadáváš sám formou ... += NEW .. tak to tam možná dáváš dvakrát .. protože přidávání eventů se pamatuje .. možná by sis měl zobrazit okno konzole a příkazem Console.WriteLine si vypisovat nějaký pomocný údaje ...

 
Nahoru Odpovědět  -1 30. dubna 9:04
Avatar
zelvicek
Člen
Avatar
zelvicek:30. dubna 13:49

Dovolím si podat své vysvětlení:

  1. je nutno pochopit smyčku zpráv (messages) okna a jejich přebírání ve vláknu. Každé okno má smyčku, která ze systému čte zprávy, na které by mělo reagovat. Čtení zpráv se děje v tzv. UI vlákně. Pokud je toto vlákno něčím zaneprázdněno (např.: hledáním v gridu), nemůže ze systému číst zprávy o clicku myši (a ani move okna, resize, ukončení,...).
  2. Řešení HONZ4 "funguje" neboť dovolí UI vláknu okna tyto čekající zprávy vykonat (kdy je ještě button disabled). Osobně se snažím DoEvents vyhnout.
  3. Myslím, že jsi zde udělal chybu v tom, že a) jsi na UI vlákno "pověsil" ne-UI funkcionalitu; b) hledáš v gridu (UI prvek) namísto v datech. Takže to předělej na Task nebo BackgroundWorker.
  4. udej použitou technologii (WF,WPF).
 
Nahoru Odpovědět  +3 30. dubna 13:49
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:30. dubna 19:18

Proč to "funguje", už napsal zelvicek. Taky napsal správně, že DoEvents je lepší se vyhnout (respektive musíš si být jistý, že můžeš bez obav použít), protože ti může spustit metodu, kterou nečekáš.
Pokud DoEvents dává do kódu začátečník, je dost pravděpodobné, že nemá dobrou koncepci aplikace. Doporučuji navrhnout aplikaci tak, aby nevadilo kliknout na zmíněné tlačítko a button vypnout jen pro oko uživatele.
Příspěvky jerryM doporučuji v tomto vlákně ignorovat (jsou nepřesné a matoucí).

zelvicek: podle nadpisu jde o WF

 
Nahoru Odpovědět 30. dubna 19:18
Avatar
JerryM
Člen
Avatar
JerryM:30. dubna 20:56

:) čau tak já sem teda ten matoucí příspěvek .. :)

klidně používej DoEvents() ... čert ví proč ti to tlačítko dělá ...
každopádně datagridview z WinFomrs vyžaduje vypnutí všech událostí tim ... -= new ....
obzvlášť když hledáš v gridu dlouho ... jde o to, že celý WinForms jsou jednovláknový ...
ono by to asi jinak s tou technologií nešlo ... bohužel z toho vyplývá mnoho jiných problémů
radši časem přejdi na WPF

 
Nahoru Odpovědět 30. dubna 20:56
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:6. května 11:26

Díky za info a pomoc.
Mám dotaz ohledně "Doporučuji navrhnout aplikaci tak, aby nevadilo kliknout na zmíněné tlačítko a button vypnout jen pro oko uživatele."

Myslíš to tak že bych si měl nastavotat někde flag (globální proměnnou). Pokud budu vyhledávat v datagridview tak ji nastavit na true a pak do každé události, kterou nechci během vyhledávání spustit přidat if:

if (flag = true)
        return;

Tím bych zamezil spouštění událostí během vyhledávání...
Takhle jsi to myslel? Nebo jak psal zelvicek pouzit vlakna? Vlákna jsem moc nepoužíval, tak si nejsem jistej jestli bych to zvládl.
Díky

Editováno 6. května 11:28
 
Nahoru Odpovědět 6. května 11:26
Avatar
zelvicek
Člen
Avatar
zelvicek:6. května 11:46

Zvládnutí vláken je více-méně nutnost. Ale ničeho se neděs, raketová věda to není.

Mkrni na https://www.codeproject.com/…or-Beginners. Článek je to dlouhý, ale popisuje problematiku celkem srozumitelně. Pokud by ses chtěl hned vrhnou na vyzkoušení, podívej se na kód na konci článku.

Věřím, že s tím problém mít nebudeš, BackgroundWorker je na inetu dobře popsaný EN i CZ.

P.S. kaju se, technologie skutečně zmíněná je.

 
Nahoru Odpovědět  +1 6. května 11:46
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:7. května 21:05

Ano třeba i tak nějak. Záleží na řešení aplikace.
Obecně můžu poradit jen:
Vlákna samozřejmě jsou dobrá věc, ale u i vláken musíš pamatovat na to, že se jednotlivá vlákna dokončí v různých časech...
Určitě je dobré myslet i na to, že uživatelé aplikací jsou schopni všeho :) U složitějších aplikací ošetřit vše, a neošetřovat to, co už ošetřené je, zabere fůru času (zvláště když se to řeší dodatečně). Proto musíš od začátku navrhovat aplikaci tak, aby ses neztrácel v logice aplikace, jejím kódu a aby nedocházelo ke konfliktům.
Takže studuj články a trénuj. Časem se to naučíš, hned nejde skoro nic. Chybami se naučíš nejvíc.

 
Nahoru Odpovědět 7. května 21:05
Avatar
HONZ4
Člen
Avatar
HONZ4:8. května 21:49

Dnes jsem se díval na včerejší příspěvek, a doplním ještě nějaký příklad:

Řekněme, že na formuláři spustím nějaké složitější filtrování (F) v jiném vlákně, které bude výsledek zobrazovat v nějakém listu (X). Pak tam bude tlačítko (T) "Vymaž list X".
Pokud stisknu tlačítko T za běhu F, tlačítko T přeruší vlákno F a vymaže list X.

A s tím tlačítkem v jednovláknové aplikaci je to podobné. Jen s tím rozdílem, že se na tlačítko za běhu F kliknout nedá. A pokud na něj klikneš tak se ten klik projeví, až poté co se F dokončí a je jedno jestli tlačítko bylo aktivní nebo ne.
V případech kdy je třeba dodržovat nějaký postup (pořadí) práce je dobré nějakým způsobem indexovat fáze postupu.

Editováno 8. května 21:51
 
Nahoru Odpovědět 8. května 21:49
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:15. května 9:53

Ahoj, omlouvám se za tak pozdní reakci. Nějak jsem nestíhal.
Takže myslíš, že použítí vláken (BackgroundWorker) můj problém nevyřeší?
Nejsnadnější postup teda bude blokování spuštěné události globální proměnnou, kterou během vyhledávání nastavím na true a pak do každé události podmínku:

if (flag == true)
        return;

Jinak děkuji za vysvětlení problému....

 
Nahoru Odpovědět 15. května 9:53
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:15. května 18:55

Právě, že vyřeší. Druhé vlákno zajistí to, že budeš moct pracovat formulářem, proto ti bude fungovat i vyřazení tlačítek (protože zprávy okna budou fungovat hned). Takže musíš vyřadit vše (nebo nějak ošetřit), co nechceš aby uživatel spustil v průběhu hledání (je jedno jestli proměnnou, nebo vyřazením (Enabled=false)). Jen to musíš udělat před spuštěním vlákna a po jeho dokončení, protože z vlákna nelze přistupovat k formu.

Editováno 15. května 18:58
 
Nahoru Odpovědět  +1 15. května 18:55
Avatar
STP
Člen
Avatar
STP:15. května 19:34

Myslím, žeby Ti stačilo event odpojit když potřebujes a zase pripojit až skončíš...

button1.Click -= new EventHandler(button1_Click);
button1.Click += new EventHandler(button1_Click);
Nahoru Odpovědět  +1 15. května 19:34
Když umřít, tak online!!!
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 17 zpráv z 17.