简体   繁体   中英

Styles not applying to headless wpf control

Goal

I have a WPF window with some nested ItemsControls . I need to extract the items into bitmaps but without actually displaying the window. So far, I have gotten through some of the hurdles of rendering the visual tree without displaying the actual window.

Problem

My problem is that the output doesn't have the styles applied to it.

Things I've tried

  • If I show the window first, then get the bitmaps, then close the window everything looks fine (styles are all applied). Though, I don't consider this "hack" to be acceptable but more a form of troubleshooting.
  • Wrapping the ContentPresenter in a ViewBox and doing a .Measure() and .Arrange() but that didn't help

I've referenced these questions to get me closer to getting things right, but alas the styles still aren't applied. I assume that I'm missing some sort of step that forces the styles to be applied. Any help would be appreciated. FYI, I'm using .Net 4 in VS 2012.

Apologies if bits of this code don't quite match up. As mentioned above there are a bunch of nested ItemsControls and for the sake of brevity I've tried to slim everything down to make it easier to follow.

Setting up the control

ucAncillary ancillaryControl = new ucAncillary(AncillaryGroups);
ancillaryControl.ApplyTemplate();
ancillaryControl.UpdateLayout();
ancillaryControl.Measure(new System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity));
ancillaryControl.Arrange(new Rect(ancillaryControl.DesiredSize));

//AncillaryGroups is the name of the ItemsControl that I want the items from
ancillaryControl.AncillaryGroups.generateContainers();

foreach (var group in AncillaryGroups)
{
    var groupControl = this.AncillaryGroups.ItemContainerGenerator.ContainerFromItem(group) as ContentPresenter;
    groupControl.ApplyTemplate();

    RenderTargetBitmap rtb = new RenderTargetBitmap((int)groupControl.DesiredSize.Width, (int)groupControl.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
    rtb.Render(groupControl);

    MemoryStream stream = new MemoryStream();
    BitmapEncoder encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(rtb));
    encoder.Save(stream);

    type.RenderedBitmap = new Bitmap(stream);
}

The GenerateContainers function mentioned above

public static void generateContainers(this ItemsControl c)
{
    IItemContainerGenerator generator = c.ItemContainerGenerator;
    GeneratorPosition position = generator.GeneratorPositionFromIndex(0);
    using (generator.StartAt(position, GeneratorDirection.Forward, true))
    {
        foreach (object o in c.Items)
        {
            DependencyObject dp = generator.GenerateNext();
            generator.PrepareItemContainer(dp);
        }
    }
}

You may have to measure and arrange the new controls again before rendering:

var groupControl = ...;
groupControl.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
groupControl.Arrange(new Rect(groupControl.DesiredSize));

This is by memory, I'll double check myself and update this if needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM