質問者
WPFで印刷するときにXamlで指定した内容で印刷したいのですが、うまくいきません

質問
-
お世話になります。
Xamlに配置した内容で印刷したいのですが、下記Xaml内のBody部分の内容が「WpfHoken.SeikyuListPrintBody」の1行のみの印字でXamlで指定した通り印刷しません。上下のヘッダー、フッターは印字します。Modelなどには各データが入っています。
VS2015 C# WPF
以下がコードです。長くてすみません。
Xaml
<Page x:Class="WpfHoken.PrintSeikyuPage" 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:WpfHoken" xmlns:app="clr-namespace:WpfHoken" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Title="請求書印刷"> <Page.Resources> <DataTemplate DataType="{x:Type app:SeikyuListPrintBody}"> <StackPanel> <!-- <Grid TextElement.FontSize="20" TextElement.FontWeight="Bold"> <Grid.ColumnDefinitions> <ColumnDefinition Width="500" /> <ColumnDefinition Width="200" /> </Grid.ColumnDefinitions> <Border Grid.Column="0" BorderBrush="Black" BorderThickness="1,1,1,1" > <TextBlock Text="ProductName" HorizontalAlignment="Center"/> </Border> <Border Grid.Column="1" BorderBrush="Black" BorderThickness="0,1,1,1" > <TextBlock Text="Price" HorizontalAlignment="Center"/> </Border> </Grid> --> <ItemsControl ItemsSource="{Binding Path=Items}" TextElement.FontSize="12"> <ItemsControl.ItemTemplate> <DataTemplate > <Grid > <Grid.RowDefinitions> <RowDefinition Height="21*" /> <!-- ヘッダ --> <RowDefinition Height="25*" /> <!-- 金額部分 --> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="113*" /> <!-- 発行年月日 --> <ColumnDefinition Width="71*" /> <!-- 御得意先 --> <ColumnDefinition Width="54*" /> <!-- 担当 --> <ColumnDefinition Width="54*" /> <!-- 区分 --> <ColumnDefinition Width="97*" /> <!-- 伝票No. --> </Grid.ColumnDefinitions> <Rectangle Grid.RowSpan="2" Grid.ColumnSpan="5" RadiusY="5" RadiusX="5" Stroke="Black" /> <Border BorderBrush="Black" BorderThickness="0,1,0,0" Grid.ColumnSpan="5" Grid.Row="1" /> <Border BorderBrush="Black" BorderThickness="1,0,0,0" Grid.RowSpan="2" Grid.Column="1" /> <Border BorderBrush="Black" BorderThickness="1,0,0,0" Grid.RowSpan="2" Grid.Column="2" /> <Border BorderBrush="Black" BorderThickness="1,0,0,0" Grid.RowSpan="2" Grid.Column="3" /> <Border BorderBrush="Black" BorderThickness="1,0,0,0" Grid.RowSpan="2" Grid.Column="4" /> <Label Content="発 行 年 月 日" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="0" /> <Label Content="項目名" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="1" /> <Label Content="点 数" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="2" /> <Label Content="件 数" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="3" /> <Label Content="料 金" Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="4" /> <!-- <Label Content="{Binding Path=,StringFormat=yyyy.MM.dd}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="1" Grid.Row="1" Grid.Column="0" /> --> <Label Content="{Binding Path=KomokuMei}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="1" Grid.Row="1" Grid.Column="1" /> <Label Content="{Binding Path=Tensu,StringFormat={}\\{0:N}}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="1" Grid.Row="1" Grid.Column="2" /> <Label Content="{Binding Path=Kensu,StringFormat={}\\{0:N}}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="1" Grid.Row="1" Grid.Column="3" /> <Label Content="{Binding Path=Ryokin,StringFormat={}\\{0:N}}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Padding="1" Grid.Row="1" Grid.Column="4" /> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </DataTemplate> </Page.Resources> <Grid Margin="30"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid Grid.Row="0" x:Name="headerGrid"> <Border BorderBrush="Black" BorderThickness="0,1" Margin="0,0,0,10"> <ContentPresenter Content="{Binding Path=Header}" HorizontalAlignment="Center" TextElement.FontSize="20"/> </Border> </Grid> <Grid Grid.Row="1" x:Name="body"> <ContentPresenter Content="{Binding Path=Body}" HorizontalAlignment="Center"/> </Grid> <Grid Grid.Row="2" x:Name="footerGrid"> <Border BorderBrush="Black" BorderThickness="0,1"> <StackPanel Margin="0,10,0,0"> <ContentPresenter Content="{Binding Path=Footer}" HorizontalAlignment="Center"/> <TextBlock HorizontalAlignment="Center" Text="{Binding Path=PageNumber,StringFormat={}Page.{0}}"/> </StackPanel> </Border> </Grid> </Grid> </Page>
そのビハインドコード
namespace WpfHoken { /// <summary>CD一覧印刷の本文部分のモデル</summary> class SeikyuListPrintBody : ListPrintBodybase<SeikyuData> { } /// <summary> /// PrintSeikyuPage.xaml の相互作用ロジック /// </summary> public partial class PrintSeikyuPage : Page { public PrintSeikyuPage() { InitializeComponent(); } } /// <summary>CD一覧印刷の1ページ分のモデル</summary> class SeikyuListPrintPageModel : PrintPageModelBase { /// <summary>1ページの項目数</summary> public const int CountPerPage = 20; public SeikyuListPrintPageModel(string header, string footer, int pageNumber, IEnumerable<SeikyuData> list) { this.Header = header; this.Footer = footer; this.PageNumber = pageNumber; this.Body = new SeikyuListPrintBody() { Items = list }; } private static IEnumerable<SeikyuListPrintPageModel> CreatePageModels(IEnumerable<SeikyuData> cds, string header = null, string footer = null) { int count = (cds.Count() + CountPerPage - 1) / CountPerPage; for (int i = 0; i < count; i++) { //1ページ分を取り出し var items = cds.Skip(CountPerPage * i).Take(CountPerPage); //印刷用モデルを作る SeikyuListPrintPageModel model = new SeikyuListPrintPageModel(header, footer, i + 1, items); yield return model; } } /// <summary>一覧から印刷用モデルを順番に生成</summary> public static IEnumerable<System.Windows.Controls.Page> CreatePages(IEnumerable<SeikyuData> cds, string header = null, string footer = null) { foreach (SeikyuListPrintPageModel model in CreatePageModels(cds, header, footer)) { PrintPage pp = new PrintPage(); pp.DataContext = model; yield return pp; } } } class SeikyuData { public string KomokuCD { get; set; } public string DateKey { get; set; } public string DateGroupKey { get; set; } public string KomokuMei { get; set; } public string StdID { get; set; } public string UserID { get; set; } public string Sequence { get; set; } public int Kensu { get; set; } // 委託先料金で確認のため public string KensuItaku { get; set; } public int Tensu { get; set; } public int Ryokin { get; set; } public int RyokinItaku { get; set; } // 委託先の単価 public int TankaItaku { get; set; } public int zRyokin { get; set; } public int Gaichu { get; set; } public string Coment { get; set; } public bool CalcLock { get; set; } public string CenterCode { get; set; } } /// <summary>通常のViewModelのようなもの</summary> class PrintSeikyuViewModel { public PrintSeikyuViewModel() { Items = new System.Collections.ObjectModel.ObservableCollection<SeikyuData>(); } public System.Collections.ObjectModel.ObservableCollection<SeikyuData> Items { get; private set; } /// <summary>ダミーデータを作る</summary> public static PrintSeikyuViewModel MakeSeikyu(string dataGroupKey) { PrintSeikyuViewModel model = new PrintSeikyuViewModel(); //System.Random rnd = new System.Random(); WpfHoken.AccountDataDataSetTableAdapters.SeikyuKomokuMasterTableTableAdapter SeikyuKomokuTableAdapter = new AccountDataDataSetTableAdapters.SeikyuKomokuMasterTableTableAdapter(); WpfHoken.AccountDataDataSetTableAdapters.KomokuTableTableAdapter komokuTableAdapter = new AccountDataDataSetTableAdapters.KomokuTableTableAdapter(); DataTable data = SeikyuKomokuTableAdapter.GetDataByGroupKey(dataGroupKey); if (data.Rows.Count > 0) { for (int k = 0; k < data.Rows.Count; k++) { bool calc = false; string txt = data.Rows[k][12].ToString(); if (txt.ToUpper() == "TRUE") calc = true; string kom = data.Rows[k][0].ToString(); DataTable dt = komokuTableAdapter.GetDataBy(kom); SeikyuData seikyu = new SeikyuData(); seikyu.KomokuCD = data.Rows[k][0].ToString(); seikyu.DateKey = data.Rows[k][1].ToString(); seikyu.DateGroupKey = data.Rows[k][2].ToString(); seikyu.UserID = data.Rows[k][3].ToString(); seikyu.StdID = data.Rows[k][4].ToString(); seikyu.Sequence = data.Rows[k][5].ToString(); seikyu.KomokuMei = dt.Rows[0][4].ToString(); int result = 0; if (int.TryParse(data.Rows[k][6].ToString(), out result)) seikyu.Kensu = result; if (int.TryParse(data.Rows[k][7].ToString(), out result)) seikyu.Tensu = result; if (int.TryParse(data.Rows[k][8].ToString(), out result)) seikyu.Ryokin = result; if (int.TryParse(data.Rows[k][9].ToString(), out result)) seikyu.zRyokin = result; if (int.TryParse(data.Rows[k][10].ToString(), out result)) seikyu.Gaichu = result; seikyu.Coment = data.Rows[k][11].ToString(); seikyu.CalcLock = calc; seikyu.CenterCode = data.Rows[k][13].ToString(); model.Items.Add(seikyu); } } return model; } } }
印刷のコア部分
/// <summary>印刷ページの基本モデル</summary> class PrintPageModelBase { public object Header { get; set; } public object Body { get; set; } public object Footer { get; set; } public int PageNumber { get; set; } public static void Print(IEnumerable<System.Windows.Controls.Page> pages) { FixedDocument doc = new FixedDocument(); foreach (System.Windows.Controls.Page p in pages) { FixedPage fp = CreateFixedPage(p); PageContent pc = new PageContent(); pc.Child = fp; doc.Pages.Add(pc); } PrintDialog dlg = new System.Windows.Controls.PrintDialog(); if (dlg.ShowDialog() == true) { System.Windows.Xps.XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(dlg.PrintQueue); doc.PrintTicket = dlg.PrintTicket; xpsdw.Write(doc, dlg.PrintTicket); } } private static FixedPage CreateFixedPage(Page page) { Action dummy = () => { }; var disp = System.Windows.Threading.Dispatcher.CurrentDispatcher; FixedPage fixpage = new FixedPage(); { Frame fm = new Frame(); fm.Content = page; //disp.Invoke(dummy, System.Windows.Threading.DispatcherPriority.Loaded);//バインディングとかいろいろさせる必要がある場合 FixedPage.SetLeft(fm, 0); FixedPage.SetTop(fm, 0); fixpage.Children.Add(fm); page.Width = 11.69 * 96; page.Height = 8.27 * 96; Size sz = new Size(page.Width, page.Height); fixpage.Width = page.Width; fixpage.Height = page.Height; fixpage.Measure(sz); fixpage.Arrange(new Rect(new Point(), sz)); fixpage.UpdateLayout(); } return fixpage; } } /// <summary>複数項目印刷する印刷ページの本文部分</summary> class ListPrintBodybase<T> { public IEnumerable<T> Items { get; set; } }
すべての返信
-
お世話になります。
> 印刷時とのことでしたが、このページを画面表示した場合は正しくBodyが表示されるのですか。
表示されていません。
> DataTemplateを用いていますが、DataTemplateを使わずにContentPresenterに・・
正しいやり方なのか分かりませんが、別ウインドウを作り、
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter.ContentTemplate>
<DataTemplate >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="21*" />
<!-- ヘッダ -->
<RowDefinition Height="25*" />
<!-- 金額部分 -->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>:
でなら、表示しています。ただ、データバインドがわからず苦慮しています。
-
たぶんこれを参考にしてるんだと思いますが、コメントアウトしてるところを戻してください。
private static FixedPage CreateFixedPage(Page page) { Action dummy = () => { }; var disp = System.Windows.Threading.Dispatcher.CurrentDispatcher; FixedPage fixpage = new FixedPage(); { Frame fm = new Frame(); fm.Content = page; //*** ここが重要 *** disp.Invoke(dummy, System.Windows.Threading.DispatcherPriority.Loaded);//バインディングとかいろいろさせる必要がある場合 //略
Frameに読み込まれるのですが、読込完了しないと表示されないのですよ。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2017年2月3日 3:44 リンクのアドレスにごみ
- 回答の候補に設定 いわさ Tak1waMVP, Moderator 2017年2月3日 4:42
-
投稿するときの編集ミスかなと思ったので指摘してなかったのですが、
/// <summary>一覧から印刷用モデルを順番に生成</summary> public static IEnumerable<System.Windows.Controls.Page> CreatePages(IEnumerable<SeikyuData> cds, string header = null, string footer = null) { foreach (SeikyuListPrintPageModel model in CreatePageModels(cds, header, footer)) { PrintPage pp = new PrintPage(); pp.DataContext = model; yield return pp; } }
でPintPageではなくPrintSeikyuPageを返さないといけないですが合ってますか?
#昼休み時間内でいそいでたので回答がちょっと手抜きだったかも
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2017年2月4日 1:23
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年2月6日 1:09