Search code examples
c#wpfbitmapresourcedictionarycontentcontrol

Loading WPF ContentControl via Resources as Bitmap does not work


For a third party product I need to convert a ContentControl to a Bitmap. Which I thought is no problem because a ContentControl is a UIElement which can be rendered in a Bitmap.

But if I plot this Bitmap than there is no image visible.

It seems that it does not work because I have the contentControl in my Application Resources and if I try to load it it is found but all properties are null or in exception status. What is going wrong here?

This is my contentControl

<ContentControl x:Key="LocationMarker" Width="356" Height="524">
<Canvas Width="356" Height="524">
  <Path Width="355.912" Height="524.355" Canvas.Left="0" Canvas.Top="-0.354675" Stretch="Fill" Fill="{DynamicResource HeaderColorBrush}" Data="...."/>
  <Path Width="150" Height="200" Canvas.Left="100" Canvas.Top="50" Stretch="Fill" Fill="{DynamicResource HeaderColorBrush}" Data="..."/>
  <Path Width="200" Height="170" Canvas.Left="78" Canvas.Top="300" Stretch="Fill" Fill="{DynamicResource HeaderColorBrush}" Data="..."/>
</Canvas>

Thats how I try to get it:

var contentControl = Application.Current.Resources.MergedDictionaries.SelectMany(x => x.MergedDictionaries).FirstOrDefault(x => x.Source.OriginalString.Contains("ContentControls.xaml"))?["LocationMarker"] as ContentControl;
  if (contentControl != null)
  {
    var renderTargetBitmap = new RenderTargetBitmap(41, 74, 96, 96, PixelFormats.Pbgra32);
    renderTargetBitmap.Render(contentControl);
    var encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
    var stream = new MemoryStream();
    encoder.Save(stream);}

Is a contentControl maybe the wrong type? Is the way of getting it by Resources wrong?

thats how it looks in the debugger: debugger screenshot

Every tip is appreciated!


Solution

  • This works for me, notice the Measure and Arrange call added to your original code.

    var contentControl = Resources["LocationMarker"] as ContentControl;
    if (contentControl != null)
    {
        contentControl.Measure(new Size(356, 524));
        contentControl.Arrange(new Rect(new Size(356, 524)));
        var target = new RenderTargetBitmap(
            (int)contentControl.RenderSize.Width, (int)contentControl.RenderSize.Height,
            96, 96, PixelFormats.Pbgra32);
        target.Render(contentControl);
    
        var encoder = new PngBitmapEncoder();
        var outputFrame = BitmapFrame.Create(target);
        encoder.Frames.Add(outputFrame);
    
        using (var file = File.OpenWrite("TestImage.png"))
        {
            encoder.Save(file);
        }
    }
    

    Code is adopted from this answer.