WPF Instantiate User control программно, чтобы отобразить его как PNG - PullRequest
5 голосов
/ 22 сентября 2009

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

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

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

Это мой код для создания пользовательского элемента управления и сохранения его в виде 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 Designer, вы можете увидеть диаграмму с несколькими пузырьками. Файл PNG содержит только область диаграммы, но без пузырьков? Почему так? Я думаю, что это проблема обновления / рендеринга, но как решить эту проблему?

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

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

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

Спасибо!

1 Ответ

2 голосов
/ 24 сентября 2009

Данные в вашей диаграмме не отображаются в вашем файле 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();
    }
}
...