2009-09-22 2 views
5

Voglio istanziare un controllo utente a livello di codice in una DLL per salvarlo in seguito come file PNG. Questo non è generalmente un problema con PngBitmapEncoder e RenderTargetBitmap.WPF Istanziare il controllo utente a livello di codice per renderlo come PNG

Questo sono le mie domande:

  • Come faccio a un'istanza del controllo? Semplicemente con il nuovo operatore?
  • Devo creare un'istanza in un thread separato?
  • Come impone al controllo di aggiornare tutti i suoi figli e di eseguire nuovamente il rendering?

Questo è il mio codice per creare un'istanza del controllo utente e salvarlo come file PNG (LetterFrequency è il controllo utente):

[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); 
     } 
    } 

Se si esegue l'applicazione in questo modo, si genera il file PNG , ma i dati, che verranno aggiunti in XAML non sono visibili, se si guarda in XAML Designer, è possibile vedere il grafico con alcune bolle. Il file png contiene solo l'area del grafico, ma non bolle? Perché quel? Penso che sia un problema di aggiornamento/rendering, ma come risolverlo?

Ecco la soluzione di Visual Studio, contiene il Progetto Console, che rende il controllo utente su un file PNG e altri due progetti del toolkit WPF per il grafico.

Date un'occhiata a questo, verrà generato il file PNG nella bin/Debug, rispettivamente, nella exe-cartella: http://www.file-upload.net/download-1904406/ChartRenderBitmap.zip.html

Spero funziona senza problemi!

Grazie!

risposta

2

I dati nel grafico non vengono visualizzati nel file PNG perché è presente un'animazione applicata alla rivelazione dei punti di dati. Dai un'occhiata al tuo controllo LetterFrequency in una finestra e vedrai che i punti si rivelano gradualmente.

Il codice acquisisce un'istantanea del controllo immediatamente dopo la sua creazione, quindi non viene visualizzato alcun dato.

Si potrebbe:

  1. avvolgere tutto questo in una finestra e dire di prendere l'istantanea dopo X secondi
  2. disabilitare tutte le animazioni in qualsiasi controllo che si vuole snapshot
  3. forse c'è un modo per animazioni "fast-forward" di programmazione, ma non riusciva a trovare una

Ecco la soluzione 1, e funziona:

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(); 
    } 
} 
+0

Grazie per la vostra soluzione interessante, ma la generazione del grafico dovrebbe essere fatto il più velocemente possibile, in modo da nessuna animazione sarebbe la migliore. Per sovrascrivere l'animazione, ho semplicemente creato un nuovo modello di controllo per il punto dati bolla, ma ora c'è un altro problema con l'elemento legenda. Dai un'occhiata al mio post di risposta! –