質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

3924閲覧

WPFの印刷処理。キューがプリンターに送れない。

ajaj

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2021/06/21 08:21

WPFで、印刷機能の付いたアプリケーションを開発しています。
環境はvisualstudio2019、.NET5.0、WPFです。

https://www.paveway.info/entry/2019/06/25/wpf_print
こちらの記事を参考に印刷ボタンに対する、関数を作成しました。一部、プリント内容はxamlのCanvas要素を指定し、変更しています。

私のコードです⇂

c#

1 private void BtnPrint_Click(object sender, RoutedEventArgs e) 2 { 3 //canvas1はcanvasのNameです。 4 var canvas = new Canvas(); 5 Canvas.SetTop(canvas1, 0); 6 Canvas.SetLeft(canvas1, 0); 7 8 canvas.Children.Add(canvas1); 9 10 var page = new FixedPage();//エラー箇所 11 12 page.Children.Add(canvas); 13 14 var queue = printDialog.PrintQueue; 15 var writer = PrintQueue.CreateXpsDocumentWriter(queue); 16 writer.Write(page); 17 }

これでアプリをデバッグすると、印刷ダイアログが表示されますが、印刷ボタンを押すと
変数pageを指定している行で、「System.InvalidOperationException: '指定された要素は、既に別の要素の論理子です。まず接続を切断してください。」
というエラーが表示されます。

ちなみにwindows10の設定画面から印刷キューを確認しても、もちろんキューは表示されていません。

必要な情報かはわかりませんがcanvas要素の中には、textbvox, image, borderの要素を内部に入れています。

ネット上にもそこそこ記事はありましたが、古いものも多く自己解決に至りません。
お手数ですが、ご教授願います。

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

注)プリンタが手元にないので未確認です。

そのエラーはすでにウィンドウ等にAddされているコントロール(canvas1)を、別のものにAddしようとしたためです。
そのため参考記事ではすべてコードで作成しています。

RemoveLogicalChildで切ることはできると思いますが、切ると当然表示も消えます。
FrameworkElement.RemoveLogicalChild(Object) メソッド (System.Windows) | Microsoft Docs

あるいはこちらは表示されているものを入れてもいいようです。
PrintDialog.PrintVisual(Visual, String) メソッド (System.Windows.Controls) | Microsoft Docs


プリンタを出すのが面倒なので、仮想プリンタでPDFに出してみましたが出ましたよ?(細かい設定とかはわからないですが

xml

1<Window 2 x:Class="Questions345252.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="450"> 7 <Grid x:Name="grid1"> 8 <Grid.RowDefinitions> 9 <RowDefinition Height="Auto" /> 10 <RowDefinition /> 11 </Grid.RowDefinitions> 12 <StackPanel> 13 <Button Click="Button_Click" Content="印刷 - Remove" /> 14 <Button Click="Button_Click_1" Content="印刷 - PrintVisual" /> 15 </StackPanel> 16 <Canvas x:Name="canvas1" Grid.Row="1"> 17 <Rectangle 18 Canvas.Left="100" 19 Canvas.Top="100" 20 Width="100" 21 Height="100" 22 Fill="Blue" /> 23 <TextBlock 24 Canvas.Left="60" 25 Canvas.Top="15" 26 Text="印刷てすと" /> 27 <Button 28 Canvas.Left="273" 29 Canvas.Top="65" 30 Width="80" 31 Content="aaa" /> 32 </Canvas> 33 </Grid> 34</Window>

cs

1using System.Printing; 2using System.Windows; 3using System.Windows.Controls; 4using System.Windows.Documents; 5 6namespace Questions345252 7{ 8 public partial class MainWindow : Window 9 { 10 public MainWindow() => InitializeComponent(); 11 12 private void Button_Click(object sender, RoutedEventArgs e) 13 { 14 var printDialog = new PrintDialog(); 15 var result = printDialog.ShowDialog(); 16 if (!result.HasValue || !result.Value) return; 17 18 // 切断 19 grid1.Children.Remove(canvas1); 20 21 var page = new FixedPage(); 22 23 // 入れる 24 page.Children.Add(canvas1); 25 26 var queue = printDialog.PrintQueue; 27 var writer = PrintQueue.CreateXpsDocumentWriter(queue); 28 writer.Write(page); 29 30 // 終わったのでこっちからも切断 31 page.Children.Remove(canvas1); 32 33 // 戻す 34 grid1.Children.Add(canvas1); 35 } 36 37 private void Button_Click_1(object sender, RoutedEventArgs e) 38 { 39 var printDialog = new PrintDialog(); 40 var result = printDialog.ShowDialog(); 41 if (!result.HasValue || !result.Value) return; 42 43 printDialog.PrintVisual(canvas1, "Questions345252"); 44 } 45 } 46}

投稿2021/06/21 14:51

編集2023/08/14 09:41
TN8001

総合スコア9326

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ajaj

2021/06/22 01:15

表示されているものを印刷することは意外と難しいことがわかりました。 紹介いただいた機能を試してみて、実際に実装をしてみたいと思います。 ありがとうございました!
ajaj

2021/06/23 09:37

一点だけ追加で教えていただきたいことがあります。 RemoveLogicalChildはどこに書けばいいのでしょうか? いろいろと試してみましたが、canvas1を引数に指定してもxamlの表示から消えません。 そもそも、そういう機能ではないのでしょうか? どうしたらいいのかを考えた結果、xamlに全く同じ、配置も被るようにcanvasを作ってNameだけ違うものを作れば、一つの接続を切断することで印刷データにすることができないかと考えました。 見当違いなことを言っていたら、申し訳ありません。
TN8001

2021/06/23 13:51

RemoveLogicalChildはprotectedメソッドです。通常呼ぶことはありません。 canvas1の親が誰かがわからなかったので、このように書きましたがちょっとわかりにくかったですね^^; 例えばGridの子であれば grid1.Children.Remove(canvas1) ですし Windowの子であれば this.Content = null で切れます(その処理の内部でRemoveLogicalChildが呼ばれているという意味) PrintDialog.PrintVisual これはやってみました? Visualはすべて?のコントロールの親クラスなので、CanvasでもWindowでも引数に入ります(試してないのでどうなるのかちょっとわからないのですが^^;
ajaj

2021/06/24 22:47

追加の回答ありがとうございます! 返信が遅くなり、申し訳ありません。コメントがつけばメールで来ると思ってましたm(._.)m print visualも試しましたが、白紙がでてきました。これもおそらく使い方のもんだいかと。。。 print logical childはこれから試して見ます! 実は私も職場の一部システムを勉強を兼ねて、作らせてもらってるのでテストを頻繁にできてません。お分かりの通り、非エンジニアです。笑 成功したら、感謝コメントさせていただきます!
TN8001

2021/06/24 23:24

検証コードを追記しました。
ajaj

2021/06/25 11:14

成功しました! わざわざ検証までしていただき、ありがとうございます。 printvisualも若干使い方が違ってましたし、 printlogicalchildメソッドも切ったり加えたりできて、こんな使い方は思いつきませんでした、かなりスマートですね。笑 これで個人的に実装したい要素はクリアできたので、あとは使い勝手を聞きながらバージョンアップしていきたいと思っています! 前回の質問から、大変お世話になりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問