2009-07-03 11 views
22

Mam następujący kod:Siła renderowania kontroli WPF w pamięci

void Test() 
{ 
    currentImage.Source = GetBitmap(); 
    RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default); 
    rtb.Render(currentImage); 
} 

Kod ten ma uczynić currentImage, który jest kontrola obrazu w moim XAML do RenderTargetBitmap.

To nie działa, RTB zwraca pusty obraz, problem jest currentImage nie czyni się jeszcze i tak oczekuje się to zachowanie, myślę ...

Aby obejść ten problem, napisałem ten Kod:

void Test() 
{ 
    currentImage.Source = GetBitmap(); 

    this.Dispatcher.BeginInvoke((Action)delegate() 
    { 
     RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default); 
     rtb.Render(currentImage); 
    }, System.Windows.Threading.DispatcherPriority.Render, null); 

} 

Zasadniczo czekam na currentImage mają być świadczone, a następnie można uzyskać go poprawnie renderowane do mojego RenderTargetBitmap.

Czy istnieje sposób, aby działał bez obejścia tego problemu? Czy może wymusić kontrolę obrazu, aby renderować w pamięci?

dziękuję!

+0

Uwaga: Jeśli masz skomplikowany układ, a pokazywane są i ukrywane elementy z konwerterami, możesz otrzymać nieprawidłowy układ końcowy. Oto, co musiałem zrobić, aby obejść to: http://stackoverflow.com/questions/41966704/wpf-xaml-control-converted-to-an-image-has-incorrect-layout/41966743#41966743 –

Odpowiedz

38

Użyj ViewBox do renderowania w pamięci

Grid grid = new System.Windows.Controls.Grid() { Background = Brushes.Blue, Width = 200, Height = 200 }; 
Viewbox viewbox = new Viewbox(); 
viewbox.Child = grid; //control to render 
viewbox.Measure(new System.Windows.Size(200, 200)); 
viewbox.Arrange(new Rect(0, 0, 200, 200)); 
viewbox.UpdateLayout(); 
RenderTargetBitmap render = new RenderTargetBitmap(200, 200, 150, 150, PixelFormats.Pbgra32); 
render.Render(viewbox); 
+0

Dziękuję tyle za to rozwiązanie! Od pewnego czasu walczę z tym, ale nie wiedziałem o sztuczce ViewBox do renderowania w pamięci. Dziękuję Ci!! – Kilhoffer

+7

To powinno być rynkowe jako zaakceptowana odpowiedź! Działa doskonale! –

+2

Możliwe jest użycie innych "pojemników" (wszystko, co pochodzi z panelu), aby osiągnąć ten sam wynik. ViewBox przeskaluje zawartość, a panele nie. –

8

myślę, że to jest BETTER answer.
The viewbox nie działał całkowicie zgodnie z oczekiwaniami, a okazało się, że jest niepotrzebny narzut.

Oto kopia tej odpowiedzi (a nie tylko link)


musisz wymusić renderowanie elementu, lub czekać na element, który ma być wydane. Następnie można użyć właściwości ActualHeight i ActualWidth.

wymusić render:

MenuItem item = new MenuItem(); 
    item.Header = "bling"; 
    item.Icon = someIcon; 
    //Force render 
    item.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
    item.Arrange(new Rect(item.DesiredSize)); 

W tym przykładzie MenuItem nie nadano wyraźną wysokość lub szerokość. Jednak wymuszenie renderowania spowoduje, że wzięty zostanie pod uwagę dostarczony tekst nagłówka i ikona.

+0

tak, ten działał dla mnie ... –

Powiązane problemy