2016-02-03 5 views
5

Ho un controllo utente complesso che mostra un'immagine e sovrappone alcuni tag sopra di esso con ombre e cose. Voglio rendere tutte quelle cose in memoria, quindi creare un'immagine di questa mappa e quindi utilizzare questa immagine nell'interfaccia utente reale. Questo è come la cosa guarda alla fine.rendere il controllo utente WPF in memoria, non sullo schermo

enter image description here

lo faccio perché l'interfaccia ha iniziato a muoversi lentamente con tutti quegli elementi intorno e sto cercando di semplificarlo. Sto andando nel modo corretto ??

Il problema qui è che creo il brainMap, lo alimento con i dati, quindi provo a creare l'imagen e BAM! non può essere fatto perché l'intero componente non è reso, l'ActualWith è zero.

Questo è come mi estrarre l'immagine dal controllo (Il metodo funziona perfettamente quando il controllo viene eseguito il rendering nella schermata)

/// <summary> 
    /// The controls need actual size, If they are not render an "UpdateLayout()" might be needed. 
    /// </summary> 
    /// <param name="control"></param> 
    /// <param name="Container"></param> 
    public static System.Windows.Controls.Image fromControlToImage(System.Windows.FrameworkElement control) 
    { 
     if (control.ActualWidth == 0) 
      throw new Exception("The control has no size, UpdateLayout is needed"); 
    // Here is where I get fired if the control was not actually rendered in the screen 

     RenderTargetBitmap rtb = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32); 
     rtb.Render(control); 

     var bitmapImage = new BitmapImage(); 
     var bitmapEncoder = new PngBitmapEncoder(); 
     bitmapEncoder.Frames.Add(BitmapFrame.Create(rtb)); 

     using (var stream = new System.IO.MemoryStream()) 
     { 
      bitmapEncoder.Save(stream); 
      stream.Seek(0, System.IO.SeekOrigin.Begin); 

      bitmapImage.BeginInit(); 
      bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
      bitmapImage.StreamSource = stream; 
      bitmapImage.EndInit(); 
     } 
     System.Windows.Controls.Image testImage = new System.Windows.Controls.Image(); 
     testImage.Source = bitmapImage; 
     return testImage; 
    } 

Se il controllo è stato parte del layout, all'inizio, l'aggiunta di un UpdateLayout risolve il problema (ecco perché ho aggiunto un'eccezione per me), ma quando il controllo viene creato dal codice e non viene mai raggiunto la pagina UpdateLayout non aiuta affatto.

Cosa posso fare per garantire il rendering di tutti gli elementi in memoria e quindi renderne un'immagine senza entrare nella pagina ?? (Dimensione fissa è passabile)

+0

E * esigenze * a far parte della struttura ad albero visuale per per renderizzare, dal modo in cui il controllo è reso (almeno ActualWidth/Height wise) dipende da tutti gli altri elementi nello stesso albero visivo. Ricordo di aver avuto un problema simile una volta, ma ho dimenticato se o come l'ho risolto alla fine. Anche se ho questa sensazione fastidiosa che non l'ho fatto, e mi sono concentrato sul rendere accettabile l'esecuzione del controllo effettivo invece di continuare una battaglia in salita. –

risposta

6

Nel tuo caso la soluzione sarebbe qualcosa di simile:

public static System.Windows.Controls.Image fromControlToImage(System.Windows.FrameworkElement control) 
{ 
    Size size = new Size(100, 100); // Or what ever size you want... 
    control.Measure(size); 
    control.Arrange(new Rect(size)); 
    control.UpdateLayout(); 
    ... 
} 

Dilanianti WPF in memoria viene spesso chiesto qui a SO:

Drawing Control to Memory

Poiché il controllo non ha un contenitore principale, y È necessario chiamare Misura e Disponi per eseguire un layout corretto.

WPF Get Size of UIElement in Memory

è necessario forzare un rendering della voce, o attendere per l'elemento da generare. È quindi possibile utilizzare le proprietà ActualHeight e ActualWidth.

Un ulteriore per il vostro scopo:

Force Rendering of a WPF Control in Memory

Propably è possibile utilizzare un viewBox per rendere in memoria

+0

Heh, immagina che, al momento, abbia avuto un problema diverso allora, faccio troppo poco con WPF in questi giorni. Uno su. –

+0

@WillemvanRumpt Grazie a SO e Google;) – Smartis