WPF Instantiate User control программно, чтобы отобразить его как PNG

Я хочу программно создать пользовательский элемент управления в DLL, чтобы впоследствии сохранить его как файл PNG. Обычно это не проблема с PngBitmapEncoder и RenderTargetBitmap.

Это мои вопросы:

  • Как создать экземпляр элемента управления? Просто с new-оператором?
  • Должен ли я создавать его в отдельном потоке?
  • Как заставить элемент управления обновить всех своих дочерних элементов и снова отобразить себя?

Это мой код для создания экземпляра пользовательского элемента управления и сохранения его как PNG-файла (LetterFrequency - это пользовательский элемент управления):

    [STAThread]
    static void Main(string[] args)
    {
        LetterFrequency let = new LetterFrequency();
        let.Width = 600;
        let.Height = 400;
        let.Background = Brushes.White;

        let.Measure(new Size(let.Width, let.Height));
        let.Arrange(new Rect(new Size(let.Width, let.Height)));

        let.UpdateLayout();

        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)let.Width, (int)let.Height, 96d, 96d, PixelFormats.Pbgra32);
        bitmap.Render(let);

        PngBitmapEncoder png = new PngBitmapEncoder();
        png.Frames.Add(BitmapFrame.Create(bitmap));

        using (Stream stm = File.Create("test.png"))
        {
            png.Save(stm);
        }
    }

Если вы запустите приложение таким образом, оно сгенерирует файл PNG, но данные, которые будут добавлены в XAML, не будут видны. Если вы посмотрите в конструктор XAML, вы увидите диаграмму с некоторыми пузырьками. Файл png содержит только область диаграммы, но без пузырей? Почему так? Я думаю, это проблема обновления / рендеринга, но как это решить?

Вот решение Visual Studio, оно содержит проект консоли, который отображает пользовательский элемент управления в файл PNG и два других проекта набора инструментов WPF для диаграммы.

Посмотрите на него, он сгенерирует файл PNG в bin / Debug соответственно в exe-папке: http://www.file-upload.net/download-1904406/ChartRenderBitmap.zip.html

Надеюсь, все заработает без проблем!

Спасибо!


person Community    schedule 22.09.2009    source источник


Ответы (1)


Данные на вашей диаграмме не отображаются в вашем файле PNG, потому что для отображения точек данных применяется анимация. Взгляните на свой элемент управления LetterFrequency в окне, и вы увидите, как точки постепенно раскрываются.

Ваш код делает снимок элемента управления сразу после его создания, поэтому вы не видите никаких данных.

Вы могли:

  1. оберните все это в окно и скажите ему сделать снимок через X секунд
  2. отключите все анимации в любых элементах управления, которые вы собираетесь делать снимки
  3. возможно, есть способ "перемотать вперед" анимацию программно, но я не смог его найти

Вот решение 1, и оно работает:

    public partial class Window1 : Window
{
    System.Windows.Threading.DispatcherTimer snapshotTimer;

    public Window1()
    {
        InitializeComponent();

        this.Width = 600;
        this.Height = 400;
        let.Width = 600;
        let.Height = 400;
        let.Background = Brushes.White;     

        this.Loaded += new RoutedEventHandler(Window1_Loaded);
    }

    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
        this.snapshotTimer = new System.Windows.Threading.DispatcherTimer();
        this.snapshotTimer.Interval = TimeSpan.FromSeconds(2);
        this.snapshotTimer.Tick += new EventHandler(snapshotTimer_Tick);
        this.snapshotTimer.IsEnabled = true;
    }

    void snapshotTimer_Tick(object sender, EventArgs e)
    {
        this.snapshotTimer.IsEnabled = false;
        WritePng();
    }

    void WritePng()
    {
        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)let.Width, (int)let.Height, 96d, 96d, PixelFormats.Pbgra32);
        bitmap.Render(let);

        PngBitmapEncoder png = new PngBitmapEncoder();
        png.Frames.Add(BitmapFrame.Create(bitmap));

        using (Stream stm = File.Create("test.png"))
        {
            png.Save(stm);
        }

        this.Close();
    }
}
person telno    schedule 23.09.2009
comment
Спасибо за интересное решение, но построение диаграммы должно производиться как можно быстрее, чтобы не было никакой анимации. Чтобы переопределить анимацию, я просто создал новый шаблон элемента управления для точки данных пузыря, но теперь есть еще одна проблема с элементом легенды. Взгляните на мой ответ! - person ; 26.09.2009