tags:

views:

642

answers:

2

Hello,

I am trying to render some XAML at runtime. My XAML is dynamically constructed in a StringBuilder. As an example, here is a sample:

StringBuilder xaml = new StringBuilder(); 
xaml.Append("<Canvas xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" "); 
xaml.Append("xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" Height=\"135\" "); 
xaml.Append("Width=\"210\" Background=\"White\" x:Name=\"Page\">"); 

string url = "http://www.mydomain.com/images/background.png"; 
xaml.Append("<Image Width=\"300\" Height=\"200\" Canvas.Left=\"0\" Canvas.Top=\"0\" "); 
xaml.Append("x:Name=\"bgImage\" Source=\""); 
xaml.Append(url); 
xaml.Append("\" />"); 

xaml.Append("</Canvas>");

Please notice the Image element in this sample. If I put this XAML in a .xaml file it runs fine. If I paste it into Blend, it works fine. However, I need to wait for this image to be downloaded and then convert the rendered XAML to a .png. In order to do this, I am using the following code:

StringReader stringReader = new StringReader(xaml.ToString()); 
XmlTextReader xmlReader = new XmlTextReader(stringReader); 
FrameworkElement frameworkElement = (FrameworkElement)(XamlReader.Load(xmlReader)); 
Size availableSize = new Size(300, 200); 
frameworkElement.Measure(availableSize); 
frameworkElement.Arrange(new Rect(availableSize)); 

BitmapSource bitmap = RenderToBitmap(frameworkElement); 
PngBitmapEncoder encoder = new PngBitmapEncoder(); 
encoder.Frames.Add(BitmapFrame.Create(bitmap)); 

FileStream fileStream = new FileStream(filename, FileMode.Create); 
encoder.Save(fileStream); 
fileStream.Close();

The problem is, the .png that is generated always ignores the Image element. I am guessing because the Image source is not downloaded. How do I generate an image from some XAML at runtime that includes an Image?

Thank you

+2  A: 

Why not just generate the object directly in C# instead of creating XAML and then having the runtime have to parse it? Doing it that way has the following benefits:

  1. Compile-time checking of your objects. The way you are doing it now might introduce run-time errors because of a fat-fingering, etc.
  2. Faster object creation. Instantiating the objects directly in C# will be faster than the parser.
  3. More maintainable. The next programmer to come along and work with this code will have an easier time with well-formatted C# vs. embedded XAML.
  4. Refactorable. You can refactor your C# code to eliminate repetitive code.
Jason Jackson
The reason why is because the XAML is being dynamically generated. The actual code is more complex than what is shown. Speed is not a concern as the XAML is being used on an asynchronous thread to generate a .png from the XAML. My concern though is actually showing an Image if an Image is used.
A: 

Might be easier to load the image yourself and then assign it to the generated Image object directly. The FrameworkElement that is created from the XAML has a x:Name for the Image instance and so you can easily find it and then assign directly to it. This way you are loading the image synchronously and not replying on it being loaded in the background which you have no real control over.

Phil Wright