Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>That example has a good start but I've found it's got a lot of unneeded junk along with it. The main thing is that you don't need to have a separate WPF project.</p> <p>Here's what to do:</p> <ul> <li>Reference PresentationCore, PresentationFramework and WindowsBase in your web project.</li> <li>Create a Canvas and other WPF objects programmatically in an STA thread.</li> <li>Call a few special methods on them to make sure they update outside of the context of a WPF app.</li> <li>Render them to an image with RenderTargetBitmap.</li> <li>Shut down the thread's dispatcher.</li> <li>Set the mime type and output the image with ASP.NET.</li> </ul> <p>To make this more efficient you could re-use the same thread rather than creating a new one for each image. In that case you would only need to clean up the dispatcher when you shut down the thread.</p> <p>Here's the full working code I have:</p> <pre><code>using System; using System.Web; using System.Threading; using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Controls; using System.Windows.Documents; public partial class _Default : System.Web.UI.Page { private byte[] imageBuffer; public void Page_Load(object sender, EventArgs e) { this.RenderImage(); Response.Clear(); Response.ContentType = @"image/png"; Response.BufferOutput = true; Response.BinaryWrite(this.imageBuffer); Response.Flush(); } public void RenderImage() { Thread worker = new Thread(new ThreadStart(this.RenderImageWorker)); worker.SetApartmentState(ApartmentState.STA); worker.Name = "RenderImageWorker"; worker.Start(); worker.Join(); } public void RenderImageWorker() { Canvas imageCanvas = new Canvas { Width = 600, Height = 200, Background = Brushes.Azure }; TextBlock tb = new TextBlock(); tb.Width = (double)400; //tb.Height = (double)200; tb.TextAlignment = TextAlignment.Center; tb.Inlines.Add(new Run("This is ")); tb.Inlines.Add(new Bold(new Run("bold"))); tb.Inlines.Add(new Run(" text.")); tb.FontSize = 30; tb.Foreground = Brushes.Blue; imageCanvas.Children.Add(tb); // Update layout imageCanvas.Measure(new Size(imageCanvas.Width, imageCanvas.Height)); imageCanvas.Arrange(new Rect(new Size(imageCanvas.Width, imageCanvas.Height))); RenderTargetBitmap bitmapRenderer = new RenderTargetBitmap((int)imageCanvas.ActualWidth, (int)imageCanvas.ActualHeight, 96, 96, PixelFormats.Pbgra32); bitmapRenderer.Render(imageCanvas); PngBitmapEncoder png = new PngBitmapEncoder(); png.Frames.Add(BitmapFrame.Create(bitmapRenderer)); using (MemoryStream memoryStream = new MemoryStream()) { png.Save(memoryStream); this.imageBuffer = memoryStream.ToArray(); } if (bitmapRenderer.Dispatcher.Thread.IsAlive) { bitmapRenderer.Dispatcher.InvokeShutdown(); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload