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

时间:2009-09-22 17:15:16

标签: wpf controls refresh instantiation

我想在DLL中以编程方式实例化用户控件,然后将其保存为PNG文件。这对于PngBitmapEncoder和RenderTargetBitmap来说通常没问题。

这是我的问题:

  • 如何实例化控件?只需使用new-operator?
  • 我是否必须在一个单独的线程中实例化它?
  • 如何强制控件更新其所有子节点并重新渲染?

这是我实例化用户控件并将其保存为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工具包的另外两个项目。

看看它,它将分别在exe文件夹的bin / Debug中生成PNG文件:http://www.file-upload.net/download-1904406/ChartRenderBitmap.zip.html

希望它没有问题!

谢谢!

1 个答案:

答案 0 :(得分:2)

图表中的数据不会在PNG文件中呈现,因为有一个动画应用于数据点的显示。看看你在一个窗口中的LetterFrequency控件,你会看到这些点逐渐显露出来。

您的代码在创建后立即拍摄控件的快照,因此您看不到任何数据。

你可以:

  1. 将所有这些包装在窗口中并告诉 它在X之后拍摄快照 秒
  2. 禁用所有动画 在你要去的任何控制中 快照
  3. 也许还有办法 “快进”动画 以编程方式,但我不能 找一个
  4. 这是解决方案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();
        }
    }