以编程方式实例化WPF用户控件以将其呈现为PNG

5
我希望能够在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工具包的其他两个项目。
请查看它,它将在bin / Debug或exe文件夹中生成PNG文件:http://www.file-upload.net/download-1904406/ChartRenderBitmap.zip.html 希望它能无问题地工作!
谢谢!
1个回答

2
您的图表数据在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();
    }
}

感谢您提供的有趣解决方案,但生成图表应尽可能快速,因此最好不要使用动画效果。为了覆盖动画效果,我简单地为气泡数据点创建了一个新的控件模板,但现在传说项出现了另一个问题。请查看我的回答帖子! - rbee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接