none
UIElement in Canvas does not render same as RenderTargetBitmap

    Question

  • I use RenderTargetBitmap to render a UIElement. The UIElement renders correctly. I then add that same UIElement to a Canvas to see what it looks like. The UIElement in the Canvas renders incorrectly. The UIElement contains a TextBlock that should Dock to the bottom, and it does not do that.

    Why would a UIElement render differently to a Canvas than to a Bitmap? How do I make it so what renders to a Canvas will render the same as rendering to a bitmap?

    What I want to do is show the UIElement as the way it will render. Then use the mouse to adjust the position of child elements of the UIElement.

    The UIElement has a height of 2400. One TextBlock should dock to the top. Another TextBlock should dock to the bottom. The Bitmap renders correctly. But the Canvas renders as if the UIElement is just high enough to fit its contents. 

    I use XamlReader.Load to create the UIElement from some static Xaml.  Then I Measure, Arrange and UpdateLayout the UIElement based on a height of 2400 and width 800. Then add that UIElement as a child element of a Canvas.  No matter what I do setting the height of the Window that contains the Canvas, and/or set the height of the Canvas, it does not render like the RenderTargetBitmap bitmap.

    thanks,

    -- XAML that contains the Canvas the UIElement is rendered to.
    
    <Window x:Class="SignPrint.View.ShowSignTester"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ShowSignTester" Height="2400" Width="800">
    
     <Grid x:Name="grdMain">
      <Grid.RowDefinitions>
       <RowDefinition Height="auto"></RowDefinition>
      </Grid.RowDefinitions>
    
       <Canvas x:Name="Canvas1" Width="800" Height="2400"
           ClipToBounds="false">
       </Canvas>
     </Grid>
    </Window>
    
    -- code that renders the xaml to the UIElement and then the
    -- Canvas and RenderTargetBitmap
      void ShowSign_Loaded(object sender, RoutedEventArgs e)
      {
       string xamlPath = "C:\\src#\\SignPrint\\SignPrint\\Signs\\TestSign2.xaml";
       FileStream fs2 = new FileStream(xamlPath, FileMode.Open);
       UIElement uie = XamlReader.Load(fs2) as UIElement;
    
       // final step that draws the sign in the UI element.
       uie.Measure(new Size(800, 2400));
       uie.Arrange(new Rect(0, 0, 800, 2400));
       uie.UpdateLayout();
    
       Canvas1.Height = 2400;
       Canvas1.Width = 800;
       this.Canvas1.Children.Add(uie);
    
       int zindex = this.Canvas1.Children.Count;
       Canvas.SetZIndex(uie, zindex);
       Canvas.SetLeft(uie, 0);
       Canvas.SetTop(uie, 0);
    
       // write the xaml rendered image as a full page bitmap.
       {
        RenderTargetBitmap bitmap = new RenderTargetBitmap(
         800, 2400, 96, 96,
         PixelFormats.Pbgra32);
        bitmap.Render(uie);
    
        // the output png file name.
        string pngPath = "c:\\srtraining\\test5.png";
        PngBitmapEncoder image = new PngBitmapEncoder();
        image.Frames.Add(BitmapFrame.Create(bitmap));
        using (Stream fsx = File.Create(pngPath))
        {
         image.Save(fsx);
        }
       }
      }
    
    
    -- the XAML being loaded by XamlReader.Load:
    
    <Grid
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     
     <Grid.Resources>
      <Style x:Key="TitleFont">
       <Setter Property="Control.FontSize" Value="260"/>
       <Setter Property="Control.FontWeight" Value="ExtraBold"/>
      </Style>
      <Style x:Key="BigFont">
       <Setter Property="Control.FontSize" Value="172"/>
       <Setter Property="Control.FontWeight" Value="ExtraBold"/>
      </Style>
      <Style x:Key="MediumFont">
       <Setter Property="Control.FontSize" Value="118"/>
       <Setter Property="Control.FontWeight" Value="ExtraBold"/>
      </Style>
     </Grid.Resources>
    
     <Border BorderBrush="Red" Margin="3" BorderThickness="3">
      <DockPanel>
       
       <StackPanel DockPanel.Dock="Top" 
             Style="{StaticResource TitleFont}"
             Orientation="Vertical">
        <TextBlock HorizontalAlignment="Center"
              Text="Top" />
       </StackPanel>
    
       <StackPanel DockPanel.Dock="Bottom" 
              Style="{StaticResource BigFont}"
             Orientation="Vertical">
        <TextBlock HorizontalAlignment="Center"
              Text="Bottom" />
       </StackPanel>
    
    
       <StackPanel VerticalAlignment="Center"
              Style="{StaticResource MediumFont}"
             Orientation="Vertical">
        <TextBlock Text="middle" 
              HorizontalAlignment="Center"/>
       </StackPanel>
    
      </DockPanel>
     </Border>
    
    </Grid>
    

     

    Wednesday, November 10, 2010 2:07 AM

Answers

  • Hi SteveRichter,

    Suice the element in the canvas can not fill the content area automatically (Grid and DockPanel can). Eve if you set the height and width to the sepcific value, the inner element remian the size of itself.

    Solution:

    1. Using Grid (or DockPanel) instead of the Canvas:
    2. Set the Height and Width both for the "uie" object:

          Canvas1.Height = 2400;
          Canvas1.Width = 800;
          this.Canvas1.Children.Add(uie);
          (uie as FrameworkElement).Width = 800;
          (uie as FrameworkElement).Height = 2400;
          int zindex = this.Canvas1.Children.Count;
          Canvas.SetZIndex(uie, zindex);
          Canvas.SetLeft(uie, 0);
          Canvas.SetTop(uie, 0);

    Please compare the Canvas and Grid panel from the document:
      Grid: http://msdn.microsoft.com/en-us/library/system.windows.controls.grid.aspx
      Canvas: http://msdn.microsoft.com/en-us/library/system.windows.controls.canvas.aspx

     

    Sincerely,
    Bob Bao

    MSDN Subscriber Support in Forum 

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download all in one code framework !
    • Marked as answer by Steve Richter Wednesday, November 10, 2010 12:24 PM
    Wednesday, November 10, 2010 4:47 AM
    Moderator