Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Michaal.K
Člen
Avatar
Michaal.K:29.4.2019 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.4.2019 14:40
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:29.4.2019 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.4.2019 18:38
 
Nahoru Odpovědět
29.4.2019 18:36
Avatar
JerryM
Člen
Avatar
JerryM:30.4.2019 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
30.4.2019 7:22
Avatar
Michaal.K
Člen
Avatar
Odpovídá na JerryM
Michaal.K:30.4.2019 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.4.2019 8:49
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:30.4.2019 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.4.2019 8:55
Avatar
JerryM
Člen
Avatar
JerryM:30.4.2019 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
30.4.2019 9:00
Avatar
JerryM
Člen
Avatar
JerryM:30.4.2019 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
30.4.2019 9:04
Avatar
zelvicek
Člen
Avatar
zelvicek:30.4.2019 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
30.4.2019 13:49
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:30.4.2019 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.4.2019 19:18
Avatar
JerryM
Člen
Avatar
JerryM:30.4.2019 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.4.2019 20:56
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:6.5.2019 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.5.2019 11:28
 
Nahoru Odpovědět
6.5.2019 11:26
Avatar
zelvicek
Člen
Avatar
zelvicek:6.5.2019 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
6.5.2019 11:46
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:7.5.2019 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.5.2019 21:05
Avatar
HONZ4
Člen
Avatar
HONZ4:8.5.2019 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.5.2019 21:51
 
Nahoru Odpovědět
8.5.2019 21:49
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:15.5.2019 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.5.2019 9:53
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:15.5.2019 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.5.2019 18:58
 
Nahoru Odpovědět
15.5.2019 18:55
Avatar
STP
Člen
Avatar
STP:15.5.2019 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
15.5.2019 19:34
Když umřít, tak online!!!
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:23.5.2019 8:35

Ahoj,
vytvořil jsem si backGroundWorker kde dělám filtraci. Mohu ve vlákně (metodě) backgroundWor­kerFiltraceDat_Do­Work přistupovat k dataGridView? Protože když ve vlákně použiji viewKatalogBin­dingSource.Fil­ter = filtrId; tak mi vyskočí chybové okno (obr v příloze).
A filtr se neprovede. V dataGridView mám všechny řádky (celou databázi) jen na prvních řádcích jsou filtrovaná data... Ale už dobře funguje blokace tlačítka během filtrace...
Pokud dám viewKatalogBin­dingSource.Fil­ter = filtrId; do metody backgroundWor­kerFiltraceDat_Run­WorkerCompleted tedy mimo vlákno. Tak filtrace v dataGridView funguje ale blokace tlačítka ne....
Díky za pomoc

 
Nahoru Odpovědět
23.5.2019 8:35
Avatar
Odpovídá na Michaal.K
Michal Štěpánek:23.5.2019 11:42

BackgroundWorker pracuje v jiném vlákně, než je hlavní UI. Pro komunikaci s uživatelem z vlákna BW, např. pro zobrazení průběhu (progressbar) se používají metody BW, např. ProgressChanged...
Mrkni se na toto video
https://channel9.msdn.com/…plikacich-CZ
je to tam krásně vysvětleno...

Nahoru Odpovědět
23.5.2019 11:42
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
zelvicek
Člen
Avatar
zelvicek:24.5.2019 7:26

Tak ještě jednou:
Udělal jsi 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.

DataGridView je vizuální prvek a operace, které má vykonat, vykonává v UI vlákně. Po dobu vykonávání úkolů UI vlákno nevykonává úkoly jiné. A pokud mu dáš mnoho dat, operace zabírají mnoho času.
IMHO je tedy lepší data uložit do paměti, a operace (hledání, filtrování, ...) vykonávat nad daty v paměti (kde má přístup i BackgroundWorker a jeho vlákno) než to nechat na DGW a UI vlákně.
P.S. neumí data hledat a filtrovat zdroj dat (třeba nějaký DB engine) ?

 
Nahoru Odpovědět
24.5.2019 7:26
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 20 zpráv z 20.