Рендеринг связанных элементов управления wpf за пределами экрана в растровое изображение

У меня есть настраиваемый элемент управления wpf для произвольной деформации обратного изображения, который использует Viewport3D и настраиваемую матрицу, а также сетку с ImageBrush ...

Я пытаюсь полностью отобразить это на растровом изображении за пределами экрана. Я могу отрендерить растровое изображение нормально (я обнаружил, что нужно вызвать .Measure () .Arrange (new Rectangle (...)) и .UpdateLayout ()) перед рендерингом, но привязка еще не завершена, поэтому сетка невидима (источник кисти изображения еще не загружен) ...

Что мне не хватает? есть ли способ блокировки дождаться завершения привязки?

[Мои попытки обработать событие "Loaded" не увенчались успехом ...]

Обновление, пример кода:

Пример кода ниже. Ожидаемый результат - синий прямоугольник размером 300x300 с логотипом переполнения стека, сжатым / повернутым в виде ромба. (попробуйте открыть конструктор DiamondControl.xaml и изменить код, чтобы URL-адрес изображения был жестко закодирован ... что интересно, этот вариант по-прежнему отсутствует в визуализированном растровом изображении, предполагая, что моя проблема не связана с привязанным URL-адресом изображения, но изображение еще не загружается)

Program.cs (консольное приложение с добавленными ссылками на System.Windows.Presentation)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ConsoleApplication3 {
    class Program {
        [STAThread]
        static void Main(string[] args) {
            // try exporting a bitmap...
            var content = new DiamondControl();
            content.DataContext = new Uri("http://sstatic.net/so/img/logo.png");
            //content.ApplyTemplate(); // this doesn't seem to work

            int width = 300, height = 300;

            var rect = new Rect(0, 0, width, height);
            content.Measure(new Size(width, height));
            content.Arrange(rect);
            //content.UpdateLayout(); // not required in this case, seems to be required if I render the control more than once

            PngBitmapEncoder encoder = new PngBitmapEncoder();
            RenderTargetBitmap render = new RenderTargetBitmap(
                width,
                height,
                96,
                96,
                PixelFormats.Pbgra32);

            render.Render(content);
            encoder.Frames.Add(BitmapFrame.Create(render));
            using (Stream s = File.Open("outputfile.png", FileMode.Create)) {
                encoder.Save(s);
            }
        }
    }
}

DiamondControl.xaml:

<UserControl x:Class="ConsoleApplication3.DiamondControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
        <Rectangle Fill="CornflowerBlue" />
        <Viewport3D>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <!-- simple diamond -->
                                <MeshGeometry3D x:Name="mesh"
                            Positions="-.5 0 0, 0 .5 0, 0 -.5 0, .5 0 0"
                            TextureCoordinates="0 1, 0 0, 1 1, 1 0" 
                            TriangleIndices="0 2 1, 2 3 1" />
                            </GeometryModel3D.Geometry>

                            <GeometryModel3D.Material>
                                <DiffuseMaterial>
                                    <DiffuseMaterial.Brush>
                                        <!--<SolidColorBrush Color="Red" />-->
                                        <ImageBrush ImageSource="{Binding}" />
                                        <!--<ImageBrush ImageSource="http://sstatic.net/so/img/logo.png" />-->
                                    </DiffuseMaterial.Brush>
                                </DiffuseMaterial>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>

                        <!-- Light source. -->
                        <AmbientLight Color="White" />
                    </Model3DGroup>
                </ModelVisual3D.Content>
            </ModelVisual3D>

            <!-- Camera. -->
            <Viewport3D.Camera>
                <OrthographicCamera Position="0 0 1"
                        LookDirection="0 0 -1"
                        UpDirection="0 1 0"
                        Width="1" />
            </Viewport3D.Camera>
        </Viewport3D>
    </Grid>
</UserControl>

person sphereinabox    schedule 09.01.2010    source источник
comment
Код рендеринга адаптирован / украден с lordzoltan.org/ blog / post / Using-WPF-to-Render-Bitmaps.aspx   -  person sphereinabox    schedule 10.01.2010
comment
Интересно, stackoverflow.com/questions/426645/ связан. Хотя приложение, с которым у меня возникла эта проблема, имеет ImageSource, привязанный к BitmapImage, который был создан вручную из относительного URI .... Я потенциально мог бы создать собственный конвертер в этом случае, чтобы изображение загружалось сразу.   -  person sphereinabox    schedule 11.01.2010
comment
Для тех, кто ищет исходное содержание ссылки, предоставленной сферой, она перемещена на lordzoltan.blogspot.com/2010/09/ - Я переместил свой блог и теперь ищу инструменты для веб-мастеров, пытаясь обновить любые входящие ссылки :)   -  person Andras Zoltan    schedule 20.09.2010


Ответы (1)


Если ваше растровое изображение соответствует веб-адресу, вы используете решение в Как отрендерить ‹image› в фоновом процессе WPF?

Кроме того, включите элемент ‹image› (даже если его размер 0x0) в свой элемент управления. Я не уверен, почему это работает, и это похоже на полную неразбериху.

person sphereinabox    schedule 24.01.2010