II 23 2009

Funkce DoEvents ve WPF

= DoEvents function in WPF

WinForm aplikace obsahovali ve tříde Application metodu DoEvents, která přepla řízení běhu aplikace dalším vláknům, čekajícím na obsloužení a poté vrátila řízení zpět. Tímto způsobem šlo např. "vynutit" překreslení UI aplikace.

WPF ale tuto funkci již v sobě integrouvanou nemá. Na internetu je možné najít několik způsobů, jak si ji napsat. Následné použití je prakticky stejné.

1.způsob

Jedná se o nekratší zápis funkce

   1: /// <summary>
   2: /// Processes all messages currently in the message queue.
   3: /// </summary>
   4: /// <remarks>
   5: /// This method can potentially cause code re-entrancy problem, so use it 
   6: /// with great care.
   7: /// </remarks>
   8: public static void DoEvents()
   9: {
  10:     Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, 
  11:         new ThreadStart(delegate { }));
  12: }

2.způsob

   1: private static DispatcherOperationCallback exitFrameCallback = new
   2:      DispatcherOperationCallback(ExitFrame);
   3:  
   4: /// <summary>
   5: /// Processes all UI messages currently in the message queue.
   6: /// </summary>
   7: public static void DoEvents()
   8: {
   9:     // Create new nested message pump.
  10:     DispatcherFrame nestedFrame = new DispatcherFrame();
  11:  
  12:     // Dispatch a callback to the current message queue, when getting called,
  13:     // this callback will end the nested message loop.
  14:     // note that the priority of this callback should be lower than the that 
  15:     // of UI event messages.
  16:     DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
  17:         DispatcherPriority.Background, exitFrameCallback, nestedFrame);
  18:     
  19:     // pump the nested message loop, the nested message loop will immediately
  20:     // process the messages left inside the message queue.
  21:     Dispatcher.PushFrame(nestedFrame);
  22:  
  23:     // If the "exitFrame" callback doesn't get finished, Abort it.
  24:     if (exitOperation.Status != DispatcherOperationStatus.Completed)
  25:     {
  26:         exitOperation.Abort();
  27:     }
  28: }
  29:  
  30: private static Object ExitFrame(Object state)
  31: {
  32:     DispatcherFrame frame = state as DispatcherFrame;
  33:  
  34:     // Exit the nested message loop.
  35:     frame.Continue = false;
  36:     return null;
  37: }
II 17 2009

Enumerace přes prvky formuláře

= Window control enumerator

Způsob, jak projít všechny ovládací prvky vložené do okna. Jelikož mohou některé prvky v rámci sebe obsahovat další ovládací prvky, je možné tyto seznamy procházet i vnořeně. Jediný rozdíl by byl v procházeném objektu. V příkladu je procházeno okno (this). Nahrazením tohoto objektu libovolným ovládacím prvkem budou vypsány prvky daného objektu.

Příklad kódu je níže:

   1: Grid windowGrid = (Grid)this.Content;
   2:  
   3: foreach (UIElement control in windowGrid.Children)
   4: {
   5:     // do sometime
   6:     MessageBox.Show(control.ToString());
   7:     // 
   8: }
II 17 2009

Ovládací prvky v průhledném panelu okna WPF aplikace

= Extend Glass Frame Into a WPF Application

Způsob, jak vykreslovat ovládací prvky u WPF aplikací v jejich poloprůhledné oblasti, je popsán v článku na MSDN:

http://msdn.microsoft.com/en-us/library/ms748975.aspx

Pro přiblížení se např. jedná o adresní a vyhledávací řádek u aplikace MS Internet Exporer 7.

IE7 with glass frame extended behind address bar.
II 17 2009

Načtení obrázku z databáze - WPF

S WPF pomalu začínám a narazil jsem na problém, kdy obrázek je načtený v databázi a já jej potřebuji načíst a dále s ním pracovat (konkrétně jej vytisknout ve formátu XPS spolu s dalšími daty).

V tomto případě je potřeba pro načtení obrázku do objektu třídy Image použít objekt třídy ImageSource, který odkazuje na načítaný obrázek. Pokud je obrázek uložen někde na disku, lze využít přímo konstruktor třídy ImageSource s přetížem, které má za parametr objekt třídy Uri s cestou k obrázku.

Tento postup však nelze použít, pokud jsou data uložena v databázy, protože jsou reprazentovaná jako poly byte[]. Po probdělém víkendu a nakopnutí na fóru Microsoftu jsem nakonec našel následující řešení. Pro načtení obrázku nakonec využívám objekty tříd MemoryStream a BitmapImage, kde třída BitmapImage je také poděděna od třídy BitmapSource a ta zas od třídy ImageSource, takže ji lze použít.

Celý kód je ve výsledku docela jednoduchý:

	   1: //data je typu byte[] a obsahuje data obrazku
	
	   2: MemoryStream ms = new MemoryStream(data); 
	
	   3: BitmapImage bi = new BitmapImage(); 
	
	   4: bi.BeginInit(); 
	
	   5: bi.StreamSource = ms; 
	
	   6: bi.EndInit(); 
	
	   7: BitmapSource bitmap = (BitmapSource)bi;