2016-04-15 4 views
0

カードゲーム用のカードを印刷できるプログラムで作業しています。プログラムには、各カードタイプのクラスとユーザーコントロールがあります。私はすべてのカードを含む大きなリストを持っています。カードを印刷するには、コード内のコントロールを動的に作成し、それらを印刷ドキュメントに追加して印刷させます。これは動作します!ここで私が使用してコントロールの世代の一例である:コントロールがpng WPFにエクスポートされるときにデータコンテキストが要素を更新しないC#

AttackCardControl cpTop = new AttackCardControl(); 
cpTop.DataContext = StateManager.CardsToPrint.ElementAt(i); 

Viewbox vb = new Viewbox() { Width = 240, Height = 336 }; 
vb.Child = cpTop; 

sp.Children.Add(vb); 

spはスタックパネルである私は、ページ上のカードを手配するために使用するには、と私はループのために、これはに含まれていることのためのイテレータです私はいくつかの小さな無関係なものと一緒に一連のforループを実行し、うまく動作します。

今、私はユーザーがカードをPNGにエクスポートできるようにする新しい機能を作成しています。私はカードをどのように印刷するかと非常に似た方法でこれを行うことにしました。これは私が使用しているものです:

for (int i = 0; i < StateManager.CardsToPrint.Count; ++i) 
{ 
    Canvas cv = new Canvas(); 
    cv.Width = 825; 
    cv.Height = 1125; 

    if (StateManager.CardsToPrint.ElementAt(i).GetType() == typeof(AttackCard)) 
    { 
     AttackCardControl cardControl = new AttackCardControl(); 
     cardControl.DataContext = StateManager.CardsToPrint.ElementAt(i); 
     cv.Children.Add(cardControl); 
    } 

    FileHandling.ExportToPng(new Uri(path + "/" + StateManager.CardsToPrint.ElementAt(i).Name + ".png"), cv); 
} 

これはリスト内のすべての攻撃カードをpngにエクスポートする必要があります。ただし、データコンテキストに関連付けられた要素は更新されません(名前、エフェクトテキスト、フレーバーテキストなど)。だから最後に、私はちょうど適切なファイル名を持つ空の攻撃カードを手に入れます。デバッグ時にそれを実行すると、DataContextにはすべての正しいデータが格納されたままになりますが、pngにエクスポートすると、ユーザーコントロールの要素のどれもその値を表示しません。ここに私のExportToPngメソッドにコードは次のとおりです。

public static void ExportToPng(Uri path, Canvas surface) 
{ 
    if (path == null) return; 

    // Save current canvas transform 
    Transform transform = surface.LayoutTransform; 
    // reset current transform (in case it is scaled or rotated) 
    surface.LayoutTransform = null; 

    // Get the size of canvas 
    System.Windows.Size size = new System.Windows.Size(surface.Width, surface.Height); 
    // Measure and arrange the surface 
    // VERY IMPORTANT 
    surface.Measure(size); 
    surface.Arrange(new Rect(size)); 

    // Create a render bitmap and push the surface to it 
    RenderTargetBitmap renderBitmap = 
     new RenderTargetBitmap(
     (int)size.Width, 
     (int)size.Height, 
     96d, 
     96d, 
     PixelFormats.Pbgra32); 
    renderBitmap.Render(surface); 

    // Create a file stream for saving image 
    using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create)) 
    { 
     // Use png encoder for our data 
     PngBitmapEncoder encoder = new PngBitmapEncoder(); 
     // push the rendered bitmap to it 
     encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); 
     // save the data to the stream 
     encoder.Save(outStream); 
    } 

    // Restore previously saved layout 
    surface.LayoutTransform = transform; 
} 

それは印刷のために働く、なぜ私は理解していないが、それはPNGにエクスポートするこのために動作しません。どんな助けでも大歓迎です。

UPDATE

私はちょうどこの問題を持っているサンプルプロジェクトを作成し、それを解決する方法を見つけるように見えることはできません。サンプルプロジェクトには、MainWindow、UserControl1、およびModel.csの3つの要素があります。

MainWindowは私がコントロールと問題を表示するために使用するものです。コードビハインドには、エラーが発生した場所のすべてのロジックが含まれています。私はこの単純な例でMVVMを気にしませんでした。ここ はXAMLです:

<Window x:Class="ExportTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:ExportTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel Name="sp" Margin="10"> 
     <Button Content="Export Control to PNG" Click="Button_Click" Width="150" Height="30"/> 
    </StackPanel> 
</Window> 

そしてここでは、背後にあるコードです:ここでは

using System; 
using System.IO; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 

namespace ExportTest 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      Model m = new Model("Testing"); 
      UserControl1 uc1 = new UserControl1(); 
      uc1.DataContext = m; 
      sp.Children.Add(uc1); 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      var dialog = new System.Windows.Forms.FolderBrowserDialog(); 
      if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) 
      { 
       string path = dialog.SelectedPath; 
       Canvas cv = new Canvas(); 
       cv.Width = 825; 
       cv.Height = 1125; 

       Model m = new Model("Testing"); 
       UserControl1 uc1 = new UserControl1(); 
       uc1.DataContext = m; 

       cv.Children.Add(uc1); 

       // The card control is losing it's data context 
       ExportToPng(new Uri(path + "/" + m.Name + ".png"), cv); 
      } 

     } 

     public void ExportToPng(Uri path, Canvas surface) 
     { 
      if (path == null) return; 

      //// Save current canvas transform 
      //Transform transform = surface.LayoutTransform; 
      //// reset current transform (in case it is scaled or rotated) 
      //surface.LayoutTransform = null; 

      // Get the size of canvas 
      Size size = new Size(surface.Width, surface.Height); 
      // Measure and arrange the surface 
      // VERY IMPORTANT 
      surface.Measure(size); 
      surface.Arrange(new Rect(size)); 

      // Create a render bitmap and push the surface to it 
      RenderTargetBitmap renderBitmap = 
       new RenderTargetBitmap(
       (int)size.Width, 
       (int)size.Height, 
       96d, 
       96d, 
       PixelFormats.Pbgra32); 
      renderBitmap.Render(surface); 

      // Create a file stream for saving image 
      using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create)) 
      { 
       // Use png encoder for our data 
       PngBitmapEncoder encoder = new PngBitmapEncoder(); 
       // push the rendered bitmap to it 
       encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); 
       // save the data to the stream 
       encoder.Save(outStream); 
      } 

      //// Restore previously saved layout 
      //surface.LayoutTransform = transform; 
     } 
    } 
} 

はUserControl1を(我々はPNGにエクスポートしようとしているユーザーコントロール)のためのXAMLです:

<UserControl x:Class="ExportTest.UserControl1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:ExportTest" 
      mc:Ignorable="d"> 
    <StackPanel Orientation="Horizontal" Background="Red"> 
     <TextBlock Text="Name: "/> 
     <TextBlock Text="{Binding Name}"/> 
    </StackPanel> 
</UserControl> 

このユーザーコントロールに必要なコードはありません。

最後に、私たちはモデルcalssを持っています。これは、UserControl1のデータコンテキストのモデルになります。ここにクラスがあります:

namespace ExportTest 
{ 
    public class Model 
    { 
     private string _Name; 

     public string Name { get { return _Name; } set { _Name = value; } } 

     public Model() 
     { 
      Name = ""; 
     } 

     public Model(string name) 
     { 
      Name = name; 
     } 
    } 
} 

これは私の正確な問題を再現します。メインウィンドウでは、我々はこのようなものを得る:あなたが見ることができるように

を、UserControl1がDataContextのをキャッチされ、名前のテストが表示されています。私もPNGボタンに輸出管理をクリックすると、これは私が私のエクスポートPNG​​ファイルのために得るものです:どういうわけか

、私のデータが欠落しています。すべての手がかりは?助けてくれてありがとう!

答えて

0
// Save current canvas transform 
Transform transform = surface.LayoutTransform; 
// reset current transform (in case it is scaled or rotated) 
surface.LayoutTransform = null; 

し、後で

// Restore previously saved layout 
surface.LayoutTransform = transform; 

は、おそらくそれがないと思うように動作しません。 Transformはクラスであり、構造体ではありません。 surface.LayoutTransformをnullに設定すると、transformもnullに設定されます。

これらの行をすべてコメントアウトしてみてください。それが動作するが、カードが回転している場合は、レイアウト変換を深くクローンするか、変更するプロパティを保存するだけです。

+0

私はこれらの3行をコメントアウトしましたが、出力に変更はありませんでした。それでも同じ問題がありました。 – Chris

+0

これは申し訳ありません。私が提案する最初のことは、いくつかの基本的なコントロールを内包したキャンバスをExporttopngに送り、問題がオブジェクト内ではなくメソッド内にあることを確認することです。がんばろう。 –