Adding children to stackpanel programmatically not

2019-06-20 02:22发布

问题:

Can anybody spot the mistake that I am doing?

Here is the code:

        StackPanel stackPanel = new StackPanel();
        stackPanel.Orientation = Orientation.Vertical;
        for (int index = _elements.Count - 1; index >= 0; index--)
        {
            FrameworkElement element = _elements[index];
            WriteableBitmap tempBitmap = new WriteableBitmap(element, null);
            Image image = new Image();
            image.Source = tempBitmap;
            stackPanel.Children.Add(image);
        }

        stackPanel.UpdateLayout();

        _bitmap = new WriteableBitmap(stackPanel, null);

        _bitmap.Invalidate();

As you can see I am creating a temporary Image and then adding it to stackpanel and then creating a final WriteableBitmap. Myy 1st children of stackpanel is of height 154 and 2nd one is of 389. After this line:

 _bitmap.Invalidate();

when I see PixelHeight it is just 389. Where did my 1st child go?

回答1:

While both of the answers given by sLedgem and bathineni are correct, it doesn't seem to fit my situation. Also why would I want to add them to the layout? If it's convenient for you, you can but in my case I want them to be in 100% memory because my helper class used basically for printing didn't have any reference to any of the UIElements present on the screen. In that case obviously I wouldn't want to pass my LayoutRoot or some other Panel to my helper class just to make this hack!

To ask the Silverlight runtime to render the elements in memory. You need to call Measure and Arrange:

So typically all I was missing was:

stackPanel.Measure(new Size(width, height));
stackPanel.Arrange(new Rect(0, 0, width, height));

before:

_bitmap = new WriteableBitmap(stackPanel, null);

And I can get rid of this line:

stackPanel.UpdateLayout();

Hope this helps someone who comes on this thread and has same problem like me where it is not feasible to find LayoutRoot in your helper class.



回答2:

stackPanel or any other panels will not render until they added to visulatree (any visual element).. means.. if you have added 100 items to stackpanel those 100 elements will not be generated until stackpanel has its visual appearence on screen..

if you dont want to show stackpanel on screen then add stackpanel and remove it immediatly. it will make stackpanel render it child elements...

OR

Create a grid or stackpanel in XAML which has 1 pixel height and width and add your stackpanel to that grid or stackpanel ... so it will not be visiable on screen and it will be rendered on background....



回答3:

bathineni is right, you need to render the stackpanel before taking a snapshot. I would suggest letting it render a frame and then grab the bitmap after it has rendered

     CompositionTarget.Rendering += CompositionTarget_Rendering;
 }

 void CompositionTarget_Rendering(object sender, EventArgs e)
  {
     _bitmap = new WriteableBitmap(stackPanel, null);
     _bitmap.Invalidate();

  }