Printing in WPF port for .NET (#1156)

* Initial files

* update toc

* Content update - print-xps-files (user story 1861941) (#1151)

* Add C# and VB sample code projects

* Fix comments

* Update C# and VB code

* Add article

* Further edits

* Reviewer requested edits

* Further edits

* Use xref to link to API

* Minor edits

* Content update - invoke-print-dialog (user story 1861941) (#1141)

* Content update including C# WPF project

* Fix link

* Remove test code

* Further doc and C# sample edits

* Add feature: printing with no print dialog

* Separate out specific page range print functionality

* Cleanup comments

* UI tweaks

* Add VB sample code project

* Code file formatting

* Update dotnet-desktop-guide/net/wpf/documents/how-to-display-print-dialog.md

Co-authored-by: Andy (Steve) De George <[email protected]>

* Add page range printing

* Minor edits

* Update dotnet-desktop-guide/net/wpf/documents/snippets/how-to-display-print-dialog/csharp/MainWindow.xaml.cs

Co-authored-by: Andy (Steve) De George <[email protected]>

* Update dotnet-desktop-guide/net/wpf/documents/how-to-display-print-dialog.md

Co-authored-by: Andy (Steve) De George <[email protected]>

* Promote example headings

* Reorganize and add detail

* Minor edits

* Add detail

* Further edits

* Further edits

* Add resource links

* Add alternative API suggestions to a tip

* Minor edit

Co-authored-by: Andy (Steve) De George <[email protected]>

* Content update - print-overview (user story 1861941) (#1153)

* Add C# and VB sample code projects

* Add article

* Add redirects

Co-authored-by: Tris Shores <[email protected]>
This commit is contained in:
Andy (Steve) De George
2021-09-24 16:16:55 -04:00
committed by GitHub
co-authored by Tris Shores
parent e96218f17e
commit bdd178c010
42 changed files with 2295 additions and 452 deletions
+475 -451
View File
@@ -1,453 +1,477 @@
{ {
"redirections": [ "redirections": [
{ {
"source_path": "dotnet-desktop-guide/net/winforms/windows-forms-overview.md", "source_path": "dotnet-desktop-guide/net/winforms/windows-forms-overview.md",
"redirect_url": "/dotnet/desktop/winforms/overview/?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/overview/?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/overview/index.md", "source_path": "dotnet-desktop-guide/framework/winforms/overview/index.md",
"redirect_url": "/dotnet/desktop/winforms/windows-forms-overview?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/windows-forms-overview?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-create-a-windows-forms-application-from-the-command-line.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-create-a-windows-forms-application-from-the-command-line.md",
"redirect_url": "/dotnet/desktop/winforms/get-started/create-app-visual-studio?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/get-started/create-app-visual-studio?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/get-started/create-app-visual-studio.md", "source_path": "dotnet-desktop-guide/framework/winforms/get-started/create-app-visual-studio.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-create-a-windows-forms-application-from-the-command-line?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-create-a-windows-forms-application-from-the-command-line?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/events-overview-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/events-overview-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/forms/events?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/forms/events?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/forms/events.md", "source_path": "dotnet-desktop-guide/framework/winforms/forms/events.md",
"redirect_url": "/dotnet/desktop/winforms/events-overview-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/events-overview-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/automatic-scaling-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/automatic-scaling-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/forms/autoscale?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/forms/autoscale?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/forms/autoscale.md", "source_path": "dotnet-desktop-guide/framework/winforms/forms/autoscale.md",
"redirect_url": "/dotnet/desktop/winforms/automatic-scaling-in-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/automatic-scaling-in-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-resize-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-resize-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/forms/how-to-position-and-resize?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/forms/how-to-position-and-resize?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/forms/how-to-position-and-resize.md", "source_path": "dotnet-desktop-guide/framework/winforms/forms/how-to-position-and-resize.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-resize-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-resize-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/layout-in-windows-forms-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/layout-in-windows-forms-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/layout.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/layout.md",
"redirect_url": "/dotnet/desktop/winforms/controls/layout-in-windows-forms-controls?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/layout-in-windows-forms-controls?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/label-control-overview-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/label-control-overview-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/labels?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/labels?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/labels.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/labels.md",
"redirect_url": "/dotnet/desktop/winforms/controls/label-control-overview-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/label-control-overview-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/varieties-of-custom-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/varieties-of-custom-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/custom?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/custom.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/custom.md",
"redirect_url": "/dotnet/desktop/winforms/controls/varieties-of-custom-controls?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/varieties-of-custom-controls?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/custom-control-painting-and-rendering.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/custom-control-painting-and-rendering.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/custom-painting-drawing.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/custom-painting-drawing.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom-control-painting-and-rendering?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/custom-control-painting-and-rendering?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-add-controls-to-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-add-controls-to-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-to-a-form?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-to-a-form?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-to-a-form.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-to-a-form.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-controls-to-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-controls-to-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-create-access-keys-for-windows-forms-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-create-access-keys-for-windows-forms-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-create-access-keys?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-create-access-keys?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-create-access-keys.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-create-access-keys.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-create-access-keys-for-windows-forms-controls?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-create-access-keys-for-windows-forms-controls?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-text-displayed-by-a-windows-forms-control.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-text-displayed-by-a-windows-forms-control.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-display-text?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-display-text?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-set-the-display-text.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-set-the-display-text.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-text-displayed-by-a-windows-forms-control?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-text-displayed-by-a-windows-forms-control?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-image-displayed-by-a-windows-forms-control.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-image-displayed-by-a-windows-forms-control.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-a-picture-to-a-control?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-a-picture-to-a-control?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-a-picture-to-a-control.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-a-picture-to-a-control.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-image-displayed-by-a-windows-forms-control?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-image-displayed-by-a-windows-forms-control?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/keyboard-input-in-a-windows-forms-application.md", "source_path": "dotnet-desktop-guide/net/winforms/keyboard-input-in-a-windows-forms-application.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/overview.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/overview.md",
"redirect_url": "/dotnet/desktop/winforms/keyboard-input-in-a-windows-forms-application?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/keyboard-input-in-a-windows-forms-application?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/using-keyboard-events.md", "source_path": "dotnet-desktop-guide/net/winforms/using-keyboard-events.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/events?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/events?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/events.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/events.md",
"redirect_url": "/dotnet/desktop/winforms/using-keyboard-events?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/using-keyboard-events?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/user-input-validation-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/user-input-validation-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/validation?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/validation?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/validation.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/validation.md",
"redirect_url": "/dotnet/desktop/winforms/user-input-validation-in-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/user-input-validation-in-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-modify-keyboard-input-to-a-standard-control.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-modify-keyboard-input-to-a-standard-control.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-change-key-press?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-change-key-press?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-change-key-press.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-change-key-press.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-modify-keyboard-input-to-a-standard-control?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-modify-keyboard-input-to-a-standard-control?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-determine-which-modifier-key-was-pressed.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-determine-which-modifier-key-was-pressed.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-check-modifier-key?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-check-modifier-key?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-check-modifier-key.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-check-modifier-key.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-determine-which-modifier-key-was-pressed?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-determine-which-modifier-key-was-pressed?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-handle-keyboard-input-at-the-form-level.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-handle-keyboard-input-at-the-form-level.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-handle-forms?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/how-to-handle-forms?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-handle-forms.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-handle-forms.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-handle-keyboard-input-at-the-form-level?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-handle-keyboard-input-at-the-form-level?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-simulate-events.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-keyboard/how-to-simulate-events.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-simulate-mouse-and-keyboard-events-in-code?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-simulate-mouse-and-keyboard-events-in-code?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/mouse-input-in-a-windows-forms-application.md", "source_path": "dotnet-desktop-guide/net/winforms/mouse-input-in-a-windows-forms-application.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/overview.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/overview.md",
"redirect_url": "/dotnet/desktop/winforms/mouse-input-in-a-windows-forms-application?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/mouse-input-in-a-windows-forms-application?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/mouse-events-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/mouse-events-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/events?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/events?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/events.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/events.md",
"redirect_url": "/dotnet/desktop/winforms/mouse-events-in-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/mouse-events-in-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/drag-and-drop-functionality-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/drag-and-drop-functionality-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/drag-and-drop?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/drag-and-drop?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/drag-and-drop.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/drag-and-drop.md",
"redirect_url": "/dotnet/desktop/winforms/drag-and-drop-functionality-in-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/drag-and-drop-functionality-in-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/mouse-pointers-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/mouse-pointers-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-manage-cursor-pointer?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-manage-cursor-pointer?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-manage-cursor-pointer.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-manage-cursor-pointer.md",
"redirect_url": "/dotnet/desktop/winforms/mouse-pointers-in-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/mouse-pointers-in-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-simulate-mouse-and-keyboard-events-in-code.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-simulate-mouse-and-keyboard-events-in-code.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-simulate-events?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-simulate-events?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-simulate-events.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-simulate-events.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-simulate-mouse-and-keyboard-events-in-code?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-simulate-mouse-and-keyboard-events-in-code?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-distinguish-between-clicks-and-double-clicks.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-distinguish-between-clicks-and-double-clicks.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-distinguish-between-clicks-and-double-clicks?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/how-to-distinguish-between-clicks-and-double-clicks?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-distinguish-between-clicks-and-double-clicks.md", "source_path": "dotnet-desktop-guide/framework/winforms/input-mouse/how-to-distinguish-between-clicks-and-double-clicks.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-distinguish-between-clicks-and-double-clicks?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-distinguish-between-clicks-and-double-clicks?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/creating-event-handlers-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/creating-event-handlers-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/forms/events?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/forms/events?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/control-type-recommendations.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/control-type-recommendations.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/custom?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/rendering-a-windows-forms-control.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/rendering-a-windows-forms-control.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/user-drawn-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/user-drawn-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/custom-painting-drawing?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-keyboard-input-works.md", "source_path": "dotnet-desktop-guide/net/winforms/how-keyboard-input-works.md",
"redirect_url": "/dotnet/desktop/winforms/input-keyboard/overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-keyboard/overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-mouse-input-works-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/how-mouse-input-works-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/input-mouse/overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/input-mouse/overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/introduction-to-wpf.md", "source_path": "dotnet-desktop-guide/net/wpf/introduction-to-wpf.md",
"redirect_url": "/dotnet/desktop/wpf/overview/?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/overview/?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/overview/index.md", "source_path": "dotnet-desktop-guide/framework/wpf/overview/index.md",
"redirect_url": "/dotnet/desktop/wpf/introduction-to-wpf?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/introduction-to-wpf?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md", "source_path": "dotnet-desktop-guide/net/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md",
"redirect_url": "/dotnet/desktop/wpf/get-started/create-app-visual-studio?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/get-started/create-app-visual-studio?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/get-started/create-app-visual-studio.md", "source_path": "dotnet-desktop-guide/framework/wpf/get-started/create-app-visual-studio.md",
"redirect_url": "/dotnet/desktop/wpf/getting-started/walkthrough-my-first-wpf-desktop-application?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/getting-started/walkthrough-my-first-wpf-desktop-application?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/wpf-windows-overview.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/wpf-windows-overview.md",
"redirect_url": "/dotnet/desktop/wpf/windows/index?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/index?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/windows/index.md", "source_path": "dotnet-desktop-guide/framework/wpf/windows/index.md",
"redirect_url": "/dotnet/desktop/wpf/app-development/wpf-windows-overview?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/app-development/wpf-windows-overview?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/dialog-boxes-overview.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/dialog-boxes-overview.md",
"redirect_url": "/dotnet/desktop/wpf/windows/dialog-boxes-overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/dialog-boxes-overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/windows/dialog-boxes-overview.md", "source_path": "dotnet-desktop-guide/framework/wpf/windows/dialog-boxes-overview.md",
"redirect_url": "/dotnet/desktop/wpf/app-development/dialog-boxes-overview?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/app-development/dialog-boxes-overview?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-window.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-window.md",
"redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-open-window-dialog-box.md", "source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-open-window-dialog-box.md",
"redirect_url": "/dotnet/desktop/wpf/app-development/how-to-open-a-window?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/app-development/how-to-open-a-window?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-dialog-box.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-dialog-box.md",
"redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/how-to-return-a-dialog-box-result.md", "source_path": "dotnet-desktop-guide/net/wpf/how-to-return-a-dialog-box-result.md",
"redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-window-dialog-box?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-message-box.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-open-a-message-box.md",
"redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-message-box?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/how-to-open-message-box?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-open-message-box.md", "source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-open-message-box.md",
"redirect_url": "/dotnet/desktop/wpf/app-development/how-to-open-a-message-box?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/app-development/how-to-open-a-message-box?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-get-and-set-the-main-application-window.md", "source_path": "dotnet-desktop-guide/net/wpf/app-development/how-to-get-and-set-the-main-application-window.md",
"redirect_url": "/dotnet/desktop/wpf/windows/how-to-get-set-main-application-window?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/windows/how-to-get-set-main-application-window?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-get-set-main-application-window.md", "source_path": "dotnet-desktop-guide/framework/wpf/windows/how-to-get-set-main-application-window.md",
"redirect_url": "/dotnet/desktop/wpf/app-development/how-to-get-and-set-the-main-application-window?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/app-development/how-to-get-and-set-the-main-application-window?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/data/data-binding-overview.md", "source_path": "dotnet-desktop-guide/net/wpf/data/data-binding-overview.md",
"redirect_url": "/dotnet/desktop/wpf/data/index?view=netdesktop-5.0", "redirect_url": "/dotnet/desktop/wpf/data/index?view=netdesktop-5.0",
"redirect_document_id": true "redirect_document_id": true
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-in-wpf.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-in-wpf.md",
"redirect_url": "/dotnet/desktop/wpf/xaml/index?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/xaml/index?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/xaml/index.md", "source_path": "dotnet-desktop-guide/framework/wpf/xaml/index.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/xaml-in-wpf?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/xaml-in-wpf?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/xaml.md", "source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/xaml.md",
"redirect_url": "/dotnet/desktop/wpf/xaml/index?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/xaml/index?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/xaml-resources-define.md", "source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/xaml-resources-define.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/styles-templates-overview.md", "source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/styles-templates-overview.md",
"redirect_url": "/dotnet/desktop/wpf/controls/styles-templates-overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/controls/styles-templates-overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/styles-templates-create-apply-style.md", "source_path": "dotnet-desktop-guide/framework/wpf/fundamentals/styles-templates-create-apply-style.md",
"redirect_url": "/dotnet/desktop/wpf/controls/how-to-create-apply-style?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/controls/how-to-create-apply-style?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/themes/how-to-create-apply-template.md", "source_path": "dotnet-desktop-guide/framework/wpf/themes/how-to-create-apply-template.md",
"redirect_url": "/dotnet/desktop/wpf/controls/how-to-create-apply-template?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/controls/how-to-create-apply-template?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-resources-define.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-resources-define.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-overview.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-overview.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/xaml-resources-define?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/xaml-resources-define?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/resources-and-code.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/resources-and-code.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-and-code?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-and-code?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-and-code.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-and-code.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/resources-and-code?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/resources-and-code?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/merged-resource-dictionaries.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/merged-resource-dictionaries.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-merged-dictionaries?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-merged-dictionaries?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-merged-dictionaries.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-merged-dictionaries.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/merged-resource-dictionaries?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/merged-resource-dictionaries?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-define-and-reference-a-resource.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-define-and-reference-a-resource.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-define-and-reference?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-define-and-reference?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-define-and-reference.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-define-and-reference.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/how-to-define-and-reference-a-resource?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-define-and-reference-a-resource?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-application-resources.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-application-resources.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-application?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-application?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-use-application.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-use-application.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/how-to-use-application-resources?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-use-application-resources?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-systemfonts.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-systemfonts.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-use-system.md", "source_path": "dotnet-desktop-guide/framework/wpf/systems/xaml-resources-how-to-use-system.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/how-to-use-systemfonts?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-use-systemfonts?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-system-fonts-keys.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-system-fonts-keys.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-systemparameters.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-systemparameters.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-system-parameters-keys.md", "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-use-system-parameters-keys.md",
"redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/systems/xaml-resources-how-to-use-system?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/migration/index.md", "source_path": "dotnet-desktop-guide/net/wpf/migration/index.md",
"redirect_url": "/dotnet/desktop/wpf/migration/differences-from-net-framework?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/wpf/migration/differences-from-net-framework?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/wpf/data/how-to-specify-the-direction-of-the-binding.md", "source_path": "dotnet-desktop-guide/net/wpf/data/how-to-specify-the-direction-of-the-binding.md",
"redirect_url": "/dotnet/desktop/wpf/data/binding-declarations-overview?view=netdesktop-5.0#binding-direction" "redirect_url": "/dotnet/desktop/wpf/data/binding-declarations-overview?view=netdesktop-5.0#binding-direction"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-tab-order-on-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-set-the-tab-order-on-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-tab-order?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-tab-order?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-set-the-tab-order.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-set-the-tab-order.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-tab-order-on-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-set-the-tab-order-on-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/index.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/index.md",
"redirect_url": "/dotnet/desktop/winforms/controls/overview?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/overview?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/overview.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/overview.md",
"redirect_url": "/dotnet/desktop/winforms/controls/index?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/index?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/autosize-property-overview.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/autosize-property-overview.md",
"redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0#automatic-sizing" "redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0#automatic-sizing"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-anchor-controls-on-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-anchor-controls-on-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-dock-and-anchor?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-dock-and-anchor?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-dock-and-anchor.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-dock-and-anchor.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-anchor-controls-on-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-anchor-controls-on-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-dock-controls-on-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-dock-controls-on-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-dock-and-anchor?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-dock-and-anchor?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-create-event-handlers-at-run-time-for-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-create-event-handlers-at-run-time-for-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-an-event-handler?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-an-event-handler?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-an-event-handler.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-add-an-event-handler.md",
"redirect_url": "/dotnet/desktop/winforms/how-to-create-event-handlers-at-run-time-for-windows-forms?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/how-to-create-event-handlers-at-run-time-for-windows-forms?view=netframeworkdesktop-4.8"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/how-to-connect-multiple-events-to-a-single-event-handler-in-windows-forms.md", "source_path": "dotnet-desktop-guide/net/winforms/how-to-connect-multiple-events-to-a-single-event-handler-in-windows-forms.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-an-event-handler?view=netdesktop-5.0#how-to-use-multiple-events-with-the-same-handler" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-add-an-event-handler?view=netdesktop-5.0#how-to-use-multiple-events-with-the-same-handler"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/margin-and-padding-in-windows-forms-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/margin-and-padding-in-windows-forms-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0#margin-and-padding" "redirect_url": "/dotnet/desktop/winforms/controls/layout?view=netdesktop-5.0#margin-and-padding"
}, },
{ {
"source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls.md", "source_path": "dotnet-desktop-guide/net/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls?view=netdesktop-5.0" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls?view=netdesktop-5.0"
}, },
{ {
"source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-make-thread-safe-calls.md", "source_path": "dotnet-desktop-guide/framework/winforms/controls/how-to-make-thread-safe-calls.md",
"redirect_url": "/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8" "redirect_url": "/dotnet/desktop/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls?view=netframeworkdesktop-4.8"
} },
] {
"source_path": "dotnet-desktop-guide/net/wpf/advanced/printing-overview.md",
"redirect_url": "/dotnet/desktop/wpf/documents/printing-overview?view=netdesktop-5.0"
},
{
"source_path": "dotnet-desktop-guide/framework/wpf/documents/printing-overview.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/printing-overview?view=netframeworkdesktop-4.8"
},
{
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-invoke-a-print-dialog.md",
"redirect_url": "/dotnet/desktop/wpf/documents/how-to-display-print-dialog?view=netdesktop-5.0"
},
{
"source_path": "dotnet-desktop-guide/framework/wpf/documents/how-to-display-print-dialog.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/how-to-invoke-a-print-dialog?view=netframeworkdesktop-4.8"
},
{
"source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-programmatically-print-xps-files.md",
"redirect_url": "/dotnet/desktop/wpf/documents/how-to-print-xps-files?view=netdesktop-5.0"
},
{
"source_path": "dotnet-desktop-guide/framework/wpf/documents/how-to-print-xps-files.md",
"redirect_url": "/dotnet/desktop/wpf/advanced/how-to-programmatically-print-xps-files?view=netframeworkdesktop-4.8"
}
]
} }
@@ -0,0 +1,65 @@
---
title: How to display a print dialog
description: Learn how to print from your application by using the System.Windows.Controls.PrintDialog class to open a standard Microsoft Windows print dialog box.
ms.date: 08/20/2021
dev_langs:
- "csharp"
- "vb"
helpviewer_keywords:
- "invoking print dialogs [WPF]"
- "print dialogs [WPF], invoking"
---
# How to display a print dialog box (WPF .NET)
Want to print from your application? You can use the <xref:System.Windows.Controls.PrintDialog> class to open a standard Microsoft Windows print dialog box. Here's how.
[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]
> [!NOTE]
> The <xref:System.Windows.Controls.PrintDialog?displayProperty=nameWithType> control used for WPF and discussed here, should not be confused with the <xref:System.Windows.Forms.PrintDialog?displayProperty=nameWithType> component of Windows Forms.
The <xref:System.Windows.Controls.PrintDialog> class provides a single control for print configuration and print job submission. The control is easy to use and can be instantiated by using XAML markup or code. The following examples create and display a `PrintDialog` instance using code.
You can use the print dialog to configure print options, such as:
- Print only a specific range of pages.
- Select from printers installed on your computer. You can use the **Microsoft XPS Document Writer** option to create these document types:
- XML Paper Specification (XPS)
- Open XML Paper Specification (OpenXPS)
## Print the whole document
This example prints all pages of an XPS document. By default, the code will:
1. Open a print dialog window that prompts the user to select a printer and start a print job.
1. Instantiate an <xref:System.Windows.Xps.Packaging.XpsDocument> object with the content of the XPS document.
1. Use the `XpsDocument` object to generate a <xref:System.Windows.Documents.DocumentPaginator> object that holds all pages of the XPS document.
1. Call the <xref:System.Windows.Controls.PrintDialog.PrintDocument%2A> method, passing in the `DocumentPaginator` object, to send all pages to the specified printer.
:::code language="csharp" source="./snippets/how-to-display-print-dialog/csharp/MainWindow.xaml.cs" id="SampleCode1":::
:::code language="vb" source="./snippets/how-to-display-print-dialog/vb/MainWindow.xaml.vb" id="SampleCode1":::
## Print a page range
Sometimes you'll only want to print a specific range of pages within an XPS document. To do this, we extend the abstract <xref:System.Windows.Documents.DocumentPaginator> class to add support for page ranges. By default, the code will:
1. Open a print dialog window that prompts the user to select a printer, specify a range of pages, and start a print job.
1. Instantiate an <xref:System.Windows.Xps.Packaging.XpsDocument> object with the content of the XPS document.
1. Use the `XpsDocument` object to generate a default <xref:System.Windows.Documents.DocumentPaginator> object that holds all pages of the XPS document.
1. Create an instance of an extended `DocumentPaginator` class that supports page ranges, passing in the default `DocumentPaginator` object and the <xref:System.Windows.Controls.PrintDialog.PageRange> struct returned by the <xref:System.Windows.Controls.PrintDialog>.
1. Call the <xref:System.Windows.Controls.PrintDialog.PrintDocument%2A> method, passing in the instance of the extended `DocumentPaginator` class, to send the specified page range to the specified printer.
:::code language="csharp" source="./snippets/how-to-display-print-dialog/csharp/MainWindow.xaml.cs" id="SampleCode2":::
:::code language="vb" source="./snippets/how-to-display-print-dialog/vb/MainWindow.xaml.vb" id="SampleCode2":::
> [!TIP]
> Although you can use the <xref:System.Windows.Controls.PrintDialog.PrintDocument%2A> method to print without opening the print dialog, for performance reasons, it's better to use the <xref:System.Printing.PrintQueue.AddJob%2A> method, or one of the many <xref:System.Windows.Xps.XpsDocumentWriter.Write%2A> and <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A> methods of the <xref:System.Windows.Xps.XpsDocumentWriter>. For more about this, see [How to print an XPS file](how-to-print-xps-files.md) and [Printing documents overview](printing-overview.md).
## See also
- <xref:System.Windows.Controls.PrintDialog>
- [Documents in WPF](/dotnet/desktop/wpf/advanced/documents-in-wpf?view=netframeworkdesktop-4.8&preserve-view=true)
- [How to print an XPS file](how-to-print-xps-files.md)
- [Printing documents overview](printing-overview.md)
- [Microsoft XPS Document Writer](/windows/win32/printdocs/microsoft-xps-document-writer)
@@ -0,0 +1,59 @@
---
title: How to print an XML Paper Specification (XPS) file
description: Learn how to print an XPS file from your application by using the System.Printing.PrintQueue.AddJob method.
ms.date: 09/16/2021
dev_langs:
- "csharp"
- "vb"
helpviewer_keywords:
- "programmatically print xps files [WPF]"
---
# How to print an XPS file (WPF .NET)
Sometimes you'll want to add a new print job to the print queue without opening a print dialog box. You can use one of the <xref:System.Printing.PrintQueue.AddJob%2A?displayProperty=nameWithType> methods to do that. Here's how.
[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)]
In the following example, we use the <xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29> method, one of the several overloads of `AddJob`, to:
- Add a new print job for an XML Paper Specification (XPS) document into the default print queue.
- Name the new job.
- Specify whether the XPS document should be validated (by using the `fastCopy` parameter).
When using the `AddJob(String, String, Boolean)` method, the value of the `fastCopy` parameter is a key consideration:
- If you set the `fastCopy` parameter to `true`, then XPS validation is skipped and the print job will spool quickly without page-by-page progress feedback.
- If you set the `fastCopy` parameter to `false`, then the thread that calls the `AddJob` method must have a [single-threaded apartment state](xref:System.Threading.ApartmentState), otherwise an exception will be thrown. For more information, see the **Remarks** section for <xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29>.
## Add new print jobs to the queue
This example adds one or more XPS documents to the default queue. The code will:
1. Use <xref:System.Threading.Tasks.Task.Run%2A?displayProperty=nameWithType> to avoid blocking the UI thread&mdash;since there's no async version of `AddJob`.
1. If the `fastCopy` parameter value is `false`, run <xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29> on a thread with [single-threaded apartment state](xref:System.Threading.ApartmentState).
1. Get a reference to the default <xref:System.Printing.PrintQueue> of the <xref:System.Printing.LocalPrintServer>.
1. Call `AddJob(String, String, Boolean)` on the print queue reference, passing in a job name, an XPS document path, and the `fastCopy` parameter.
If the queue isn't paused and the printer is working, then a print job will automatically begin printing when it reaches the top of the print queue.
> [!TIP]
> To avoid the **Save Output File As** dialog when adding a print job to the default queue, ensure that your default printer isn't **Microsoft XPS Document Writer**, **Microsoft Print to PDF**, or other print-to-file options.
:::code language="csharp" source="./snippets/how-to-print-xps-files/csharp/MainWindow.xaml.cs" id="SampleCode1":::
:::code language="vb" source="./snippets/how-to-print-xps-files/vb/MainWindow.xaml.vb" id="SampleCode1":::
> [!TIP]
> You can also print XPS files by using:
>
> - <xref:System.Windows.Controls.PrintDialog.PrintDocument%2A?displayProperty=nameWithType> or <xref:System.Windows.Controls.PrintDialog.PrintVisual%2A?displayProperty=nameWithType> methods.
> - <xref:System.Windows.Xps.XpsDocumentWriter.Write%2A?displayProperty=nameWithType> and <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A?displayProperty=nameWithType> methods.
>
> For more information, see [How to display a print dialog box](how-to-display-print-dialog.md) and [Printing documents overview](printing-overview.md).
## See also
- <xref:System.Printing.PrintQueue.AddJob%2A?displayProperty=nameWithType>
- [Documents in WPF](/dotnet/desktop/wpf/advanced/documents-in-wpf?view=netframeworkdesktop-4.8&preserve-view=true)
- [How to display a print dialog box](how-to-display-print-dialog.md)
- [Printing documents overview](printing-overview.md)
@@ -0,0 +1,136 @@
---
title: Printing documents overview
description: Learn about the printing and print system management APIs available with Windows Presentation Foundation (WPF).
ms.date: 09/22/2021
ms.topic: overview
dev_langs:
- "csharp"
- "vb"
helpviewer_keywords:
- "print path [WPF], XPS"
- "printers [WPF], XPSDrv-based"
- "printing [WPF]"
- "PrintQueue class PrintServer class [WPF]"
- "XML Paper Specification (XPS) file format"
- "XPS (XML Paper Specification) file format"
- "XPSDrv-based printers"
- "GDI print path [WPF]"
---
# Printing documents overview (WPF .NET)
With Microsoft .NET, application developers using Windows Presentation Foundation (WPF) have a rich set of printing and print system management APIs. The core of this functionality is the XML Paper Specification (XPS) file format and the XPS print path.
## About XPS
XPS is an electronic document format, a spool file format, and a page description language. It's an open document format that uses XML, Open Packaging Conventions, and other industry standards to create cross-platform documents. XPS simplifies the process by which digital documents are created, shared, printed, viewed, and archived. For more on XPS, see [XPS Documents](/windows/desktop/printdocs/documents).
## XPS print path
The [XPS print path](/windows-hardware/drivers/print/windows-print-path-overview) is a Windows feature that redefines how printing is handled in Windows applications. XPS print path can replace:
- Document presentation languages, such as Rich Text Format or Portable Document Format.
- Print spooler formats, such as Windows Metafile or Enhanced Metafile (EMF).
- Page description languages, such as Printer Command Language or PostScript.
As a result, the XPS print path maintains the XPS format from application publication down to final processing in the printer driver or device.
The print spooler for XPS documents supports both the XPS print path and the GDI print path. The XPS print path natively consumes an XPS spool file and requires an XPS printer driver. The XPS print path is built on the [XPS printer driver](/windows-hardware/drivers/print/xpsdrv-printer-driver) (XPSDrv) model.
The benefits of the XPS print path include:
- WYSIWYG print support.
- Native support of advanced color profiles, such as 32 bits per channel, the CMYK color model, named-colors, n-inks, and transparencies and gradients.
- Improved print performance&mdash;XPS features and enhancements are only available to applications that target the XPS print path.
- Industry standard XPS format.
For basic print scenarios, a simple and intuitive API is available with a standard UI for print configuration and job submission. For advanced scenarios, the API supports UI customization or no UI at all, synchronous or asynchronous printing, and batch printing capabilities. Both simple and advanced options provide print support in full or partial trust modes.
XPS was designed with extensibility in mind, so features and capabilities can be added to XPS in a modular manner. Extensibility features include:
- A print schema that supports rapid extension of device capabilities. The public portion of the schema is regularly updated to add desired device capabilities. For more information, see [Extensible architecture](/windows-hardware/drivers/print/extensible-architecture).
- An extensible filter pipeline that XPSDrv drivers use to support both direct and scalable printing of XPS documents. For more information, see [XPSDrv printer drivers](/windows-hardware/drivers/print/xpsdrv-printer-drivers).
### Print path architecture
WPF applications natively support the XPS print path, and can use XPS print APIs to print directly to the XPSDrv driver. If the target print queue of the write operation doesn't have an XPSDrv driver, then the <xref:System.Windows.Xps.XpsDocumentWriter.Write%2A> and <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A> methods of the <xref:System.Windows.Xps.XpsDocumentWriter> class will automatically convert content from XPS to GDI format, for the GDI print path.
The following illustration shows the print subsystem and defines the portions provided by Microsoft and independent software and hardware vendors.
![Screenshot showing the XPS print system.](~/framework/wpf/advanced/media/printing-overview/xml-paper-specification-print-system.png)
### Basic XPS printing
WPF has a printing API that supports both basic and advanced printing features. For those applications that don't require extensive print customization or access to the complete XPS feature set, basic print support might suffice. Basic print support is provided through a [PrintDialog](#printdialog) control that requires minimal configuration, has a familiar UI, and supports many XPS features.
#### PrintDialog
The <xref:System.Windows.Controls.PrintDialog?displayProperty=nameWithType> control provides a single entry point for UI, configuration, and XPS job submission. To learn how to instantiate and use the control, see [How to display a print dialog](how-to-display-print-dialog.md).
### Advanced XPS printing
To access the complete set of XPS features, use the advanced printing API. Several relevant APIs are described in this section, including [PrintTicket](#printticket-and-printcapabilities), [PrintCapabilities](#printticket-and-printcapabilities), [PrintServer](#printserver-and-printqueue), [PrintQueue](#printserver-and-printqueue), and [XpsDocumentWriter](#xpsdocumentwriter). For a complete list of XPS print path APIs, see the <xref:System.Windows.Xps> and <xref:System.Printing> namespaces.
#### PrintTicket and PrintCapabilities
The <xref:System.Printing.PrintTicket> and <xref:System.Printing.PrintCapabilities> classes are the foundation of advanced XPS features. Both objects contain XML formatted structures of print-oriented features that are defined by the print schema. The features include duplexing, collation, two-sided printing, and stapling. A `PrintTicket` instructs a printer how to process a print job. The `PrintCapabilities` class defines the capabilities of a printer. By querying the capabilities of a printer, a `PrintTicket` can be created that takes full advantage of a printer's supported features. Similarly, unsupported features can be avoided.
The following example queries the `PrintCapabilities` of a printer and creates a `PrintTicket` using code.
:::code language="csharp" source="./snippets/printing-overview/csharp/MainWindow.xaml.cs" id="GetPrintTicket":::
:::code language="vb" source="./snippets/printing-overview/vb/MainWindow.xaml.vb" id="GetPrintTicket":::
#### PrintServer and PrintQueue
The <xref:System.Printing.PrintServer> class represents a network print server, and the <xref:System.Printing.PrintQueue> class represents a printer and the output job queue associated with it. Together, these APIs support advanced management of the print jobs for a server. A `PrintServer`, or one of its derived classes, is used to manage a `PrintQueue`.
The following example creates a <xref:System.Printing.LocalPrintServer> and accesses the local computer's <xref:System.Printing.PrintQueueCollection> using code.
:::code language="csharp" source="./snippets/printing-overview/csharp/MainWindow.xaml.cs" id="GetPrintQueues":::
:::code language="vb" source="./snippets/printing-overview/vb/MainWindow.xaml.vb" id="GetPrintQueues":::
#### XpsDocumentWriter
<xref:System.Windows.Xps.XpsDocumentWriter>, with its many <xref:System.Windows.Xps.XpsDocumentWriter.Write%2A> and <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A> methods, is used to add XPS documents to a <xref:System.Printing.PrintQueue>. For example, the <xref:System.Windows.Xps.XpsDocumentWriter.Write%28System.Windows.Documents.FixedDocumentSequence%2CSystem.Printing.PrintTicket%29> method is used to synchronously add an XPS document with a print ticket to a queue. The <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%28System.Windows.Documents.FixedDocumentSequence%2CSystem.Printing.PrintTicket%29> method is used to asynchronously add an XPS document with a print ticket to a queue.
The following example creates an `XpsDocumentWriter` and adds XPS documents, both synchronously and asynchronously, to a `PrintQueue` using code.
:::code language="csharp" source="./snippets/printing-overview/csharp/MainWindow.xaml.cs" id="PrintXpsDocument":::
:::code language="vb" source="./snippets/printing-overview/vb/MainWindow.xaml.vb" id="PrintXpsDocument":::
## GDI print path
Although WPF applications natively support the XPS print path, they can also output to the GDI print path by calling one of the <xref:System.Windows.Xps.XpsDocumentWriter.Write%2A> or <xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A> methods of the <xref:System.Windows.Xps.XpsDocumentWriter> class and selecting the print queue for a non-XpsDrv printer.
For applications that don't require XPS functionality or support, the current GDI print path remains unchanged. For more about the GDI print path and the various XPS conversion options, see [Microsoft XPS document converter (MXDC)](/windows/win32/printdocs/microsoft-xps-document-converter--mxdc-) and [XPSDrv printer drivers](/windows-hardware/drivers/print/xpsdrv-printer-drivers).
## XPSDrv driver model
The XPS print path improves spooler efficiency by using XPS as the native print spool format when printing to an XPS-enabled printer or driver. Unlike EMF, which represents application output as a series of calls into GDI for rendering services, XPS spool format represents the document. So, when XPS spool files are output to an XPS-based printer driver, they don't require further interpretation as the drivers operate directly on data in that format. This capability eliminates the data and color space conversions required for EMF files and GDI-based print drivers.
The simplified spooling process eliminates the need to generate an intermediate spool file, such as an EMF data file, before the document is spooled. With smaller spool file sizes, the XPS print path can reduce network traffic and improve print performance. Compared with their EMF equivalents, XPS spool file sizes are typically reduced when using the XPS print path. Spool file size reduction is done through several mechanisms:
- **Font subsetting**, which only stores the characters used within a document in the XPS file.
- **Advanced graphics support**, which natively supports transparency and gradient primitives to avoid rasterization of XPS content.
- **Identification of common resources**, such as an image of a corporate logo that's used multiple times in a document. Common resources are treated as shared resources and are only loaded once.
- **ZIP compression**, which is used on all XPS documents.
The XPS spool file size might not be reduced if a vector graphic is highly complex, multi-layered, or inefficiently written. Unlike GDI spool files, XPS files embed device fonts and computer-based fonts for screen display purposes, though both kinds of fonts are subsetted and printer drivers can remove device fonts before transmitting the file to the printer.
> [!TIP]
> You can also print XPS files by using <xref:System.Printing.PrintQueue.AddJob%2A?displayProperty=nameWithType> methods. For more information, see [How to print XPS files](how-to-print-xps-files.md).
## See also
- <xref:System.Windows.Controls.PrintDialog>
- <xref:System.Windows.Xps.XpsDocumentWriter>
- <xref:System.Windows.Xps.Packaging.XpsDocument>
- <xref:System.Printing.PrintTicket>
- <xref:System.Printing.PrintCapabilities>
- <xref:System.Printing.PrintServer>
- <xref:System.Printing.PrintQueue>
- [How-to topics](/dotnet/desktop/wpf/advanced/printing-how-to-topics?view=netframeworkdesktop-4.8&preserve-view=true)
- [Documents in WPF](/dotnet/desktop/wpf/advanced/documents-in-wpf?view=netframeworkdesktop-4.8&preserve-view=true)
- [XPS documents](/windows/desktop/printdocs/documents)
- [Document serialization and storage](/dotnet/desktop/wpf/advanced/document-serialization-and-storage?view=netframeworkdesktop-4.8&preserve-view=true)
- [Microsoft XPS document converter (MXDC)](/windows/win32/printdocs/microsoft-xps-document-converter--mxdc-)
@@ -0,0 +1,9 @@
<Application x:Class="CodeSampleCsharp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleCsharp"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleCsharp.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="149" Width="509">
<Grid Margin="0,0,0,10">
<Label Content="Select XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="78"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,71,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top"/>
<CheckBox x:Name="cbxHidePrintDialog" Content="Hide print dialog" HorizontalAlignment="Left" Margin="124,77,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.376,-0.054"/>
</Grid>
</Window>
@@ -0,0 +1,240 @@
using System;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Xps.Packaging;
using Microsoft.Win32;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for MainWindow.xaml.
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Events.
btnBrowse.Click += BtnBrowse_Click;
btnPrint.Click += BtnPrint_Click;
}
private void BtnBrowse_Click(object sender, RoutedEventArgs e)
{
// Configure an open file dialog box.
OpenFileDialog openFileDialog = new()
{
FileName = "Document",
DefaultExt = ".xps",
Filter = "Text documents (.xps)|*.xps"
};
// Show open file dialog box.
bool? result = openFileDialog.ShowDialog();
// Process open file dialog box results.
if (result == true)
{
// Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName;
}
}
private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
// Check the file exists.
if (!File.Exists(txtXpsFilePath.Text))
{
MessageBox.Show("First select an XPS file.");
return;
}
// Get the print dialog visibility.
bool hidePrintDialog = cbxHidePrintDialog.IsChecked == true;
// Print whole document.
bool isPrinted = PrintWholeDocument(txtXpsFilePath.Text, hidePrintDialog);
MessageBox.Show($"PrintWholeDocument {(isPrinted ? "printed" : "failed to print")}.");
// Print a specific range of document pages as specified in the print dialog.
if (!hidePrintDialog)
{
isPrinted = PrintDocumentPageRange(txtXpsFilePath.Text);
MessageBox.Show($"PrintDocumentPageRange {(isPrinted ? "printed" : "failed to print")}.");
}
}
// <SampleCode1>
/// <summary>
/// Print all pages of an XPS document.
/// Optionally, hide the print dialog window.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file</param>
/// <param name="hidePrintDialog">Whether to hide the print dialog window (shown by default)</param>
/// <returns>Whether the document printed</returns>
public static bool PrintWholeDocument(string xpsFilePath, bool hidePrintDialog = false)
{
// Create the print dialog object and set options.
PrintDialog printDialog = new();
if (!hidePrintDialog)
{
// Display the dialog. This returns true if the user presses the Print button.
bool? isPrinted = printDialog.ShowDialog();
if (isPrinted != true)
return false;
}
// Print the whole document.
try
{
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Create a paginator for all pages in the selected document.
DocumentPaginator docPaginator = fixedDocSeq.DocumentPaginator;
// Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}");
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
// </SampleCode1>
// <SampleCode2>
/// <summary>
/// Print a specific range of pages within an XPS document.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file</param>
/// <returns>Whether the document printed</returns>
public static bool PrintDocumentPageRange(string xpsFilePath)
{
// Create the print dialog object and set options.
PrintDialog printDialog = new()
{
UserPageRangeEnabled = true
};
// Display the dialog. This returns true if the user presses the Print button.
bool? isPrinted = printDialog.ShowDialog();
if (isPrinted != true)
return false;
// Print a specific page range within the document.
try
{
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Create a paginator for all pages in the selected document.
DocumentPaginator docPaginator = fixedDocSeq.DocumentPaginator;
// Check whether a page range was specified in the print dialog.
if (printDialog.PageRangeSelection == PageRangeSelection.UserPages)
{
// Create a document paginator for the specified range of pages.
docPaginator = new DocPaginator(fixedDocSeq.DocumentPaginator, printDialog.PageRange);
}
// Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}");
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
/// <summary>
/// Extend the abstract DocumentPaginator class to support page range printing. This class is based on the following online resources:
///
/// https://www.thomasclaudiushuber.com/2009/11/24/wpf-printing-how-to-print-a-pagerange-with-wpfs-printdialog-that-means-the-user-can-select-specific-pages-and-only-these-pages-are-printed/
///
/// https://social.msdn.microsoft.com/Forums/vstudio/en-US/9180e260-0791-4f2d-962d-abcb22ba8d09/how-to-print-multiple-page-ranges-with-wpf-printdialog
///
/// https://social.msdn.microsoft.com/Forums/en-US/841e804b-9130-4476-8709-0d2854c11582/exception-quotfixedpage-cannot-contain-another-fixedpagequot-when-printing-to-the-xps-document?forum=wpf
/// </summary>
public class DocPaginator : DocumentPaginator
{
private readonly DocumentPaginator _documentPaginator;
private readonly int _startPageIndex;
private readonly int _endPageIndex;
private readonly int _pageCount;
public DocPaginator(DocumentPaginator documentPaginator, PageRange pageRange)
{
// Set document paginator.
_documentPaginator = documentPaginator;
// Set page indices.
_startPageIndex = pageRange.PageFrom - 1;
_endPageIndex = pageRange.PageTo - 1;
// Validate and set page count.
if (_startPageIndex >= 0 &&
_endPageIndex >= 0 &&
_startPageIndex <= _documentPaginator.PageCount - 1 &&
_endPageIndex <= _documentPaginator.PageCount - 1 &&
_startPageIndex <= _endPageIndex)
_pageCount = _endPageIndex - _startPageIndex + 1;
}
public override bool IsPageCountValid => true;
public override int PageCount => _pageCount;
public override IDocumentPaginatorSource Source => _documentPaginator.Source;
public override Size PageSize { get => _documentPaginator.PageSize; set => _documentPaginator.PageSize = value; }
public override DocumentPage GetPage(int pageNumber)
{
DocumentPage documentPage = _documentPaginator.GetPage(_startPageIndex + pageNumber);
// Workaround for "FixedPageInPage" exception.
if (documentPage.Visual is FixedPage fixedPage)
{
var containerVisual = new ContainerVisual();
foreach (object child in fixedPage.Children)
{
var childClone = (UIElement)child.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(child, null);
FieldInfo parentField = childClone.GetType().GetField("_parent", BindingFlags.Instance | BindingFlags.NonPublic);
if (parentField != null)
{
parentField.SetValue(childClone, null);
containerVisual.Children.Add(childClone);
}
}
return new DocumentPage(containerVisual, documentPage.Size, documentPage.BleedBox, documentPage.ContentBox);
}
return documentPage;
}
}
// </SampleCode2>
}
}
@@ -0,0 +1,9 @@
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleVb"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,6 @@
Class Application
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
End Class
@@ -0,0 +1,11 @@
Imports System.Windows
'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found.
'1st parameter: where theme specific resource dictionaries are located
'(used if a resource is not found in the page,
' or application resource dictionaries)
'2nd parameter: where the generic resource dictionary is located
'(used if a resource is not found in the page,
'app, and any theme specific resource dictionaries)
<Assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)>
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>CodeSampleVb</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Import Include="System.Windows" />
<Import Include="System.Windows.Controls" />
<Import Include="System.Windows.Data" />
<Import Include="System.Windows.Documents" />
<Import Include="System.Windows.Input" />
<Import Include="System.Windows.Media" />
<Import Include="System.Windows.Media.Imaging" />
<Import Include="System.Windows.Navigation" />
<Import Include="System.Windows.Shapes" />
</ItemGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleVb.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="149" Width="509">
<Grid Margin="0,0,0,10">
<Label Content="Select XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="78"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,71,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top"/>
<CheckBox x:Name="cbxHidePrintDialog" Content="Hide print dialog" HorizontalAlignment="Left" Margin="124,77,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.376,-0.054"/>
</Grid>
</Window>
@@ -0,0 +1,270 @@
Imports System
Imports System.IO
Imports System.Reflection
Imports System.Windows.Xps.Packaging
Imports Microsoft.Win32
Namespace CodeSampleVb
Partial Public Class MainWindow
Inherits Window
''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
Public Sub New()
InitializeComponent()
' Events.
AddHandler btnBrowse.Click, AddressOf BtnBrowse_Click
AddHandler btnPrint.Click, AddressOf BtnPrint_Click
End Sub
Private Sub BtnBrowse_Click(sender As Object, e As RoutedEventArgs)
' Configure an open file dialog box.
Dim openFileDialog As New OpenFileDialog With {
.FileName = "Document",
.DefaultExt = ".xps",
.Filter = "Text documents (.xps)|*.xps"
}
' Show open file dialog box.
Dim result As Boolean? = openFileDialog.ShowDialog()
' Process open file dialog box results.
If result = True Then
' Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName
End If
End Sub
Private Sub BtnPrint_Click(sender As Object, e As RoutedEventArgs)
' Check the file exists.
If Not File.Exists(txtXpsFilePath.Text) Then
MessageBox.Show("First select an XPS file.")
Return
End If
' Get the print dialog visibility.
Dim hidePrintDialog = cbxHidePrintDialog.IsChecked = True
Dim isPrinted As Boolean
' Print whole document.
isPrinted = PrintWholeDocument(txtXpsFilePath.Text, hidePrintDialog)
MessageBox.Show($"PrintWholeDocument {If(isPrinted, "printed", "failed to print")}.")
' Print a specific range of document pages as specified in the print dialog.
If Not hidePrintDialog Then
isPrinted = PrintDocumentPageRange(txtXpsFilePath.Text)
MessageBox.Show($"PrintDocumentPageRange {If(isPrinted, "printed", "failed to print")}.")
End If
End Sub
' <SampleCode1>
''' <summary>
''' Print all pages of an XPS document.
''' Optionally, print all pages without showing a print dialog window.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file</param>
''' <param name="hidePrintDialog">Whether to hide the print dialog window (shown by default)</param>
''' <returns>Whether the document printed</returns>
Public Shared Function PrintWholeDocument(xpsFilePath As String, Optional hidePrintDialog As Boolean = False) As Boolean
' Create the print dialog object and set options.
Dim printDialog As New PrintDialog
If Not hidePrintDialog Then
' Display the dialog. This returns true if the user presses the Print button.
Dim isPrinted As Boolean? = printDialog.ShowDialog()
If isPrinted <> True Then Return False
End If
' Print the whole document.
Try
' Open the selected document.
Dim xpsDocument As New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Create a paginator for all pages in the selected document.
Dim docPaginator As DocumentPaginator = fixedDocSeq.DocumentPaginator
' Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}")
Return True
Catch e As Exception
MessageBox.Show(e.Message)
Return False
End Try
End Function
' </SampleCode1>
' <SampleCode2>
''' <summary>
''' Print a specific range of pages within an XPS document.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file</param>
''' <returns>Whether the document printed</returns>
Public Shared Function PrintDocumentPageRange(xpsFilePath As String) As Boolean
' Create the print dialog object and set options.
Dim printDialog As New PrintDialog With {
.UserPageRangeEnabled = True
}
' Display the dialog. This returns true if the user presses the Print button.
Dim isPrinted As Boolean? = printDialog.ShowDialog()
If isPrinted <> True Then Return False
' Print a specific page range within the document.
Try
' Open the selected document.
Dim xpsDocument As New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Create a paginator for all pages in the selected document.
Dim docPaginator As DocumentPaginator = fixedDocSeq.DocumentPaginator
' Check whether a page range was specified in the print dialog.
If printDialog.PageRangeSelection = PageRangeSelection.UserPages Then
' Create a document paginator for the specified range of pages.
docPaginator = New DocPaginator(fixedDocSeq.DocumentPaginator, printDialog.PageRange)
End If
' Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}")
Return True
Catch e As Exception
MessageBox.Show(e.Message)
Return False
End Try
End Function
' <summary>
' Extend the abstract DocumentPaginator class to support page range printing.
' This class is based on the following online resources:
' https://www.thomasclaudiushuber.com/2009/11/24/wpf-printing-how-to-print-a-pagerange-with-wpfs-printdialog-
' that-means-the-user-can-select-specific-pages-and-only-these-pages-are-printed/
' https://social.msdn.microsoft.com/Forums/vstudio/en-US/9180e260-0791-4f2d-962d-abcb22ba8d09/how-to-print-
' multiple-page-ranges-with-wpf-printdialog
' https://social.msdn.microsoft.com/Forums/en-US/841e804b-9130-4476-8709-0d2854c11582/exception-quotfixedpage-
' cannot-contain-another-fixedpagequot-when-printing-to-the-xps-document?forum=wpf
' </summary>
Public Class DocPaginator
Inherits DocumentPaginator
Private ReadOnly _documentPaginator As DocumentPaginator
Private ReadOnly _startPageIndex As Integer
Private ReadOnly _endPageIndex As Integer
Private ReadOnly _pageCount As Integer
Public Sub New(documentPaginator As DocumentPaginator, pageRange As PageRange)
' Set document paginator.
_documentPaginator = documentPaginator
' Set page indices.
_startPageIndex = pageRange.PageFrom - 1
_endPageIndex = pageRange.PageTo - 1
' Validate And set page count.
If _startPageIndex >= 0 AndAlso
_endPageIndex >= 0 AndAlso
_startPageIndex <= _documentPaginator.PageCount - 1 AndAlso
_endPageIndex <= _documentPaginator.PageCount - 1 AndAlso
_startPageIndex <= _endPageIndex Then
_pageCount = _endPageIndex - _startPageIndex + 1
End If
End Sub
Public Overrides ReadOnly Property IsPageCountValid As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property PageCount As Integer
Get
Return _pageCount
End Get
End Property
Public Overrides ReadOnly Property Source As IDocumentPaginatorSource
Get
Return _documentPaginator.Source
End Get
End Property
Public Overrides Property PageSize As Size
Get
Return _documentPaginator.PageSize
End Get
Set(value As Size)
_documentPaginator.PageSize = value
End Set
End Property
Public Overrides Function GetPage(pageNumber As Integer) As DocumentPage
Dim documentPage As DocumentPage = _documentPaginator.GetPage(_startPageIndex + pageNumber)
' Workaround for "FixedPageInPage" exception.
If documentPage.Visual.GetType() Is GetType(FixedPage) Then
Dim fixedPage As FixedPage = documentPage.Visual
Dim containerVisual = New ContainerVisual()
For Each child As Object In fixedPage.Children
Dim childClone = CType(child.[GetType]().GetMethod("MemberwiseClone", BindingFlags.Instance Or BindingFlags.NonPublic).Invoke(child, Nothing), UIElement)
Dim parentField As FieldInfo = childClone.[GetType]().GetField("_parent", BindingFlags.Instance Or BindingFlags.NonPublic)
If parentField IsNot Nothing Then
parentField.SetValue(childClone, Nothing)
containerVisual.Children.Add(childClone)
End If
Next
Return New DocumentPage(containerVisual, documentPage.Size, documentPage.BleedBox, documentPage.ContentBox)
End If
Return documentPage
End Function
End Class
' </SampleCode2>
End Class
End Namespace
@@ -0,0 +1,9 @@
<Application x:Class="CodeSampleCsharp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleCsharp"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
@@ -0,0 +1,14 @@
<Window x:Class="CodeSampleCsharp.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="149" Width="509">
<Grid Margin="0,0,0,10">
<Label Content="Enter the path to a folder that contains XPS files" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="447" FontSize="14" x:Name="txtFolderPath" Height="21"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,71,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<CheckBox x:Name="cbxValidateXps" Content="Validate XPS files" HorizontalAlignment="Left" Margin="137,78,0,0" VerticalAlignment="Top" IsChecked="True"/>
</Grid>
</Window>
@@ -0,0 +1,137 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Printing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for MainWindow.xaml.
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void BtnPrint_Click(object sender, RoutedEventArgs e)
{
// Check that the folder exists.
if (!Directory.Exists(txtFolderPath.Text))
{
MessageBox.Show("First select a valid folder path.");
return;
}
// Check whether any XPS files exist in the folder.
string[] xpsFilePaths = Directory.GetFiles(path: txtFolderPath.Text, searchPattern: "*.xps");
if (xpsFilePaths.Length == 0)
{
MessageBox.Show("No XPS files found.");
return;
}
// Determine whether XPS validation is needed.
bool fastCopy = cbxValidateXps.IsChecked == false;
// Batch add a collection of XPS files to the print queue.
// Run asynchronously to avoid blocking the UI thread.
bool isAllPrinted = await BatchAddToPrintQueueAsync(xpsFilePaths, fastCopy);
// Show result message.
MessageBox.Show($"{(isAllPrinted ? "Added" : "Failed to add")} all documents to the print queue.");
}
// <SampleCode1>
/// <summary>
/// Asyncronously, add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
/// Handle the thread apartment state required by the PrintQueue.AddJob method.
/// </summary>
/// <param name="xpsFilePaths">A collection of XPS documents.</param>
/// <param name="fastCopy">Whether to validate the XPS documents.</param>
/// <returns>Whether all documents were added to the print queue.</returns>
public static async Task<bool> BatchAddToPrintQueueAsync(IEnumerable<string> xpsFilePaths, bool fastCopy = false)
{
bool allAdded = true;
// Queue some work to run on the ThreadPool.
// Wait for completion without blocking the calling thread.
await Task.Run(() =>
{
if (fastCopy)
allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy);
else
{
// Create a thread to call the PrintQueue.AddJob method.
Thread newThread = new(() =>
{
allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy);
});
// Set the thread to single-threaded apartment state.
newThread.SetApartmentState(ApartmentState.STA);
// Start the thread.
newThread.Start();
// Wait for thread completion. Blocks the calling thread,
// which is a ThreadPool thread.
newThread.Join();
}
});
return allAdded;
}
/// <summary>
/// Add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
/// </summary>
/// <param name="xpsFilePaths">A collection of XPS documents.</param>
/// <param name="fastCopy">Whether to validate the XPS documents.</param>
/// <returns>Whether all documents were added to the print queue.</returns>
public static bool BatchAddToPrintQueue(IEnumerable<string> xpsFilePaths, bool fastCopy)
{
bool allAdded = true;
// To print without getting the "Save Output File As" dialog, ensure
// that your default printer is not the Microsoft XPS Document Writer,
// Microsoft Print to PDF, or other print-to-file option.
// Get a reference to the default print queue.
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
// Iterate through the document collection.
foreach (string xpsFilePath in xpsFilePaths)
{
// Get document name.
string xpsFileName = Path.GetFileName(xpsFilePath);
try
{
// The AddJob method adds a new print job for an XPS
// document into the print queue, and assigns a job name.
// Use fastCopy to skip XPS validation and progress notifications.
// If fastCopy is false, the thread that calls PrintQueue.AddJob
// must have a single-threaded apartment state.
PrintSystemJobInfo xpsPrintJob =
defaultPrintQueue.AddJob(jobName: xpsFileName, documentPath: xpsFilePath, fastCopy);
// If the queue is not paused and the printer is working, then jobs will automatically begin printing.
Debug.WriteLine($"Added {xpsFileName} to the print queue.");
}
catch (PrintJobException e)
{
allAdded = false;
Debug.WriteLine($"Failed to add {xpsFileName} to the print queue: {e.Message}\r\n{e.InnerException}");
}
}
return allAdded;
}
// </SampleCode1>
}
}
@@ -0,0 +1,9 @@
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleVb"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,6 @@
Class Application
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
End Class
@@ -0,0 +1,11 @@
Imports System.Windows
'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found.
'1st parameter: where theme specific resource dictionaries are located
'(used if a resource is not found in the page,
' or application resource dictionaries)
'2nd parameter: where the generic resource dictionary is located
'(used if a resource is not found in the page,
'app, and any theme specific resource dictionaries)
<Assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)>
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>CodeSampleVb</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Import Include="System.Windows" />
<Import Include="System.Windows.Controls" />
<Import Include="System.Windows.Data" />
<Import Include="System.Windows.Documents" />
<Import Include="System.Windows.Input" />
<Import Include="System.Windows.Media" />
<Import Include="System.Windows.Media.Imaging" />
<Import Include="System.Windows.Navigation" />
<Import Include="System.Windows.Shapes" />
</ItemGroup>
</Project>
@@ -0,0 +1,14 @@
<Window x:Class="CodeSampleVb.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="149" Width="509">
<Grid Margin="0,0,0,10">
<Label Content="Enter the path to a folder that contains XPS files" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="447" FontSize="14" x:Name="txtFolderPath" Height="21"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,71,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<CheckBox x:Name="cbxValidateXps" Content="Validate XPS files" HorizontalAlignment="Left" Margin="137,78,0,0" VerticalAlignment="Top" IsChecked="True"/>
</Grid>
</Window>
@@ -0,0 +1,133 @@
Imports System.IO
Imports System.Printing
Imports System.Threading
Namespace CodeSampleVb
Partial Public Class MainWindow
Inherits Window
''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
Public Sub New()
InitializeComponent()
End Sub
Private Async Sub BtnPrint_Click(sender As Object, e As RoutedEventArgs)
' Check that the folder exists.
If Not Directory.Exists(txtFolderPath.Text) Then
MessageBox.Show("First select a valid folder path.")
Return
End If
' Check whether any XPS files exist in the folder.
Dim xpsFilePaths = Directory.GetFiles(path:=txtFolderPath.Text, searchPattern:="*.xps")
If xpsFilePaths.Length = 0 Then
MessageBox.Show("No XPS files found.")
Return
End If
' Determine whether XPS validation is needed.
Dim fastCopy As Boolean = cbxValidateXps.IsChecked = False
' Batch add a collection of XPS files to the print queue.
' Run asynchronously to avoid blocking the UI thread.
Dim isAllPrinted As Boolean = Await BatchAddToPrintQueueAsync(xpsFilePaths, fastCopy)
' Show result message.
MessageBox.Show($"{If(isAllPrinted, "Added", "Failed to add")} all documents to the print queue.")
End Sub
' <SampleCode1>
''' <summary>
''' Asyncronously, add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
''' Handle the thread apartment state required by the PrintQueue.AddJob method.
''' </summary>
''' <param name="xpsFilePaths">A collection of XPS documents.</param>
''' <param name="fastCopy">Whether to validate the XPS documents.</param>
''' <returns>Whether all documents were added to the print queue.</returns>
Public Shared Async Function BatchAddToPrintQueueAsync(xpsFilePaths As IEnumerable(Of String), Optional fastCopy As Boolean = False) As Task(Of Boolean)
Dim isAllPrinted As Boolean = True
' Queue some work to run on the ThreadPool.
' Wait for completion without blocking the calling thread.
Await Task.Run(
Sub()
If fastCopy Then
isAllPrinted = BatchAddToPrintQueue(xpsFilePaths, fastCopy)
Else
' Create a thread to call the PrintQueue.AddJob method.
Dim newThread As New Thread(
Sub()
isAllPrinted = BatchAddToPrintQueue(xpsFilePaths, fastCopy)
End Sub
)
' Set the thread to single-threaded apartment state.
newThread.SetApartmentState(ApartmentState.STA)
' Start the thread.
newThread.Start()
' Wait for thread completion. Blocks the calling thread,
' which is a ThreadPool thread.
newThread.Join()
End If
End Sub
)
Return isAllPrinted
End Function
''' <summary>
''' Add a batch of XPS documents to the print queue using a PrintQueue.AddJob method.
''' </summary>
''' <param name="xpsFilePaths">A collection of XPS documents.</param>
''' <param name="fastCopy">Whether to validate the XPS documents.</param>
''' <returns>Whether all documents were added to the print queue.</returns>
Public Shared Function BatchAddToPrintQueue(xpsFilePaths As IEnumerable(Of String), fastCopy As Boolean) As Boolean
Dim isAllPrinted As Boolean = True
' To print without getting the "Save Output File As" dialog, ensure
' that your default printer is not the Microsoft XPS Document Writer,
' Microsoft Print to PDF, or other print-to-file option.
' Get a reference to the default print queue.
Dim defaultPrintQueue As PrintQueue = LocalPrintServer.GetDefaultPrintQueue()
' Iterate through the document collection.
For Each xpsFilePath As String In xpsFilePaths
' Get document name.
Dim xpsFileName As String = Path.GetFileName(xpsFilePath)
Try
' The AddJob method adds a new print job for an XPS
' document into the print queue, and assigns a job name.
' Use fastCopy to skip XPS validation and progress notifications.
' If fastCopy is false, the thread that calls PrintQueue.AddJob
' must have a single-threaded apartment state.
Dim xpsPrintJob As PrintSystemJobInfo = defaultPrintQueue.AddJob(jobName:=xpsFileName, documentPath:=xpsFilePath, fastCopy)
' If the queue is not paused and the printer is working, then jobs will automatically begin printing.
Debug.WriteLine($"Added {xpsFileName} to the print queue.")
Catch e As PrintJobException
isAllPrinted = False
Debug.WriteLine($"Failed to add {xpsFileName} to the print queue: {e.Message}\r\n{e.InnerException}")
End Try
Next
Return isAllPrinted
End Function
' </SampleCode1>
End Class
End Namespace
@@ -0,0 +1,9 @@
<Application x:Class="CodeSampleCsharp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleCsharp"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleCsharp.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="234" Width="509">
<Grid Margin="0,0,0,-6" Loaded="Grid_Loaded">
<Label Content="Select an XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,148,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<ComboBox x:Name="cmbPrinters" HorizontalAlignment="Left" Margin="32,90,0,0" VerticalAlignment="Top" Width="372"/>
<Label Content="Select a printer" HorizontalAlignment="Left" Margin="27,66,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20" Click="BtnBrowse_Click"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
</Grid>
</Window>
@@ -0,0 +1,186 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Printing;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using Microsoft.Win32;
namespace CodeSampleCsharp
{
/// <summary>
/// Interaction logic for MainWindow.xaml.
/// </summary>
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
foreach (PrintQueue printQueue in GetPrintQueues())
{
// Add printers that have at least one relevant print options.
PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
if (printCapabilites.CollationCapability.Contains(Collation.Collated) ||
printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) ||
printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
cmbPrinters.Items.Add(printQueue.Name);
}
// Select the first printer.
if (cmbPrinters.Items.Count > 0)
cmbPrinters.SelectedIndex = 0;
}
private void BtnBrowse_Click(object sender, RoutedEventArgs e)
{
// Configure an open file dialog box.
OpenFileDialog openFileDialog = new()
{
FileName = "Document",
DefaultExt = ".xps",
Filter = "Text documents (.xps)|*.xps"
};
// Show open file dialog box.
bool? result = openFileDialog.ShowDialog();
// Process open file dialog box results.
if (result == true)
{
// Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName;
}
}
private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
// Check the XPS file exists.
if (!File.Exists(txtXpsFilePath.Text))
{
MessageBox.Show("First select an XPS file.");
return;
}
// Get the print queue for the selected printer.
PrintQueue selectedPrintQueue = GetPrintQueues().SingleOrDefault(x => Equals(x.Name, cmbPrinters.SelectedItem.ToString()));
// Get a print ticket with modified print options for the selected printer.
PrintTicket printTicket = GetPrintTicket(selectedPrintQueue);
// Send the XPS document to the selected printer.
PrintXpsDocumentAsync(txtXpsFilePath.Text, selectedPrintQueue, printTicket);
// Show modified print options.
List<string> optionList = new();
if (printTicket.Collation == Collation.Collated)
optionList.Add("Collated");
if (printTicket.Duplexing == Duplexing.TwoSidedLongEdge)
optionList.Add("TwoSidedLongEdge");
if (printTicket.Stapling == Stapling.StapleDualLeft)
optionList.Add("StapleDualLeft");
var options = optionList.Count > 0 ? string.Join(", ", optionList) : "None";
// Show result message.
MessageBox.Show($"Sent {Path.GetFileName(txtXpsFilePath.Text)} to the printer.\r\nPrint options: {options}");
}
// <GetPrintQueues>
/// <summary>
/// Return a collection of print queues, which individually hold the features or states
/// of a printer as well as common properties for all print queues.
/// </summary>
/// <returns>A collection of print queues.</returns>
public static PrintQueueCollection GetPrintQueues()
{
// Create a LocalPrintServer instance, which represents
// the print server for the local computer.
LocalPrintServer localPrintServer = new();
// Get the default print queue on the local computer.
//PrintQueue printQueue = localPrintServer.DefaultPrintQueue;
// Get all print queues on the local computer.
PrintQueueCollection printQueueCollection = localPrintServer.GetPrintQueues();
// Return a collection of print queues, which individually hold the features or states
// of a printer as well as common properties for all print queues.
return printQueueCollection;
}
// </GetPrintQueues>
// <GetPrintTicket>
/// <summary>
/// Returns a print ticket, which is a set of instructions telling a printer how
/// to set its various features, such as duplexing, collating, and stapling.
/// </summary>
/// <param name="printQueue">The print queue to print to.</param>
/// <returns>A print ticket.</returns>
public static PrintTicket GetPrintTicket(PrintQueue printQueue)
{
PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();
// Get a default print ticket from printer.
PrintTicket printTicket = printQueue.DefaultPrintTicket;
// Modify the print ticket.
if (printCapabilites.CollationCapability.Contains(Collation.Collated))
printTicket.Collation = Collation.Collated;
if (printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
printTicket.Stapling = Stapling.StapleDualLeft;
// Returns a print ticket, which is a set of instructions telling a printer how
// to set its various features, such as duplexing, collating, and stapling.
return printTicket;
}
// </GetPrintTicket>
// <PrintXpsDocument>
/// <summary>
/// Asynchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocumentAsync(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
// Create an XpsDocumentWriter object for the print queue.
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Asynchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket);
}
/// <summary>
/// Synchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocument(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
// Create an XpsDocumentWriter object for the print queue.
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Synchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.Write(fixedDocSeq, printTicket);
}
// </PrintXpsDocument>
}
}
@@ -0,0 +1,9 @@
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CodeSampleVb"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,6 @@
Class Application
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
End Class
@@ -0,0 +1,11 @@
Imports System.Windows
'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found.
'1st parameter: where theme specific resource dictionaries are located
'(used if a resource is not found in the page,
' or application resource dictionaries)
'2nd parameter: where the generic resource dictionary is located
'(used if a resource is not found in the page,
'app, and any theme specific resource dictionaries)
<Assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)>
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>CodeSampleVb</RootNamespace>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Import Include="System.Windows" />
<Import Include="System.Windows.Controls" />
<Import Include="System.Windows.Data" />
<Import Include="System.Windows.Documents" />
<Import Include="System.Windows.Input" />
<Import Include="System.Windows.Media" />
<Import Include="System.Windows.Media.Imaging" />
<Import Include="System.Windows.Navigation" />
<Import Include="System.Windows.Shapes" />
</ItemGroup>
</Project>
@@ -0,0 +1,16 @@
<Window x:Class="CodeSampleVb.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"
mc:Ignorable="d"
Title="Print an XPS file" Height="234" Width="509">
<Grid Margin="0,0,0,-6" Loaded="Grid_Loaded">
<Label Content="Select an XPS file" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Print" HorizontalAlignment="Left" Margin="32,148,0,0" FontSize="14" Width="51" x:Name="btnPrint" Height="28" VerticalAlignment="Top" Click="BtnPrint_Click"/>
<ComboBox x:Name="cmbPrinters" HorizontalAlignment="Left" Margin="32,90,0,0" VerticalAlignment="Top" Width="372"/>
<Label Content="Select a printer" HorizontalAlignment="Left" Margin="27,66,0,0" VerticalAlignment="Top" FontSize="11" Height="25" Width="339"/>
<Button Content="Browse" HorizontalAlignment="Left" Margin="428,35,0,0" VerticalAlignment="Top" Width="48" x:Name="btnBrowse" Height="20" Click="BtnBrowse_Click"/>
<TextBox HorizontalAlignment="Left" Margin="32,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="391" FontSize="14" x:Name="txtXpsFilePath" Height="21"/>
</Grid>
</Window>
@@ -0,0 +1,191 @@
Imports System.IO
Imports System.Printing
Imports System.Windows.Xps
Imports System.Windows.Xps.Packaging
Imports Microsoft.Win32
Namespace CodeSampleVb
Partial Public Class MainWindow
Inherits Window
''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
Public Sub New()
InitializeComponent()
End Sub
Private Sub Grid_Loaded(sender As Object, e As RoutedEventArgs)
For Each printQueue As PrintQueue In GetPrintQueues()
' Add printers that have at least one relevant print options.
Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()
If printCapabilites.CollationCapability.Contains(Collation.Collated) _
OrElse printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) _
OrElse printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
cmbPrinters.Items.Add(printQueue.Name)
End If
Next
' Select the first printer.
If cmbPrinters.Items.Count > 0 Then cmbPrinters.SelectedIndex = 0
End Sub
Private Sub BtnBrowse_Click(sender As Object, e As RoutedEventArgs)
' Configure an open file dialog box.
Dim openFileDialog As OpenFileDialog = New OpenFileDialog() With {
.FileName = "Document",
.DefaultExt = ".xps",
.Filter = "Text documents (.xps)|*.xps"
}
' Show open file dialog box.
Dim result As Boolean? = openFileDialog.ShowDialog()
' Process open file dialog box results.
If result = True Then
' Show selected XPS file path.
txtXpsFilePath.Text = openFileDialog.FileName
End If
End Sub
Private Sub BtnPrint_Click(sender As Object, e As RoutedEventArgs)
' Check the XPS file exists.
If Not File.Exists(txtXpsFilePath.Text) Then
MessageBox.Show("First select an XPS file.")
Return
End If
' Get the print queue for the selected printer.
Dim selectedPrintQueue As PrintQueue = GetPrintQueues().SingleOrDefault(Function(x) Equals(x.Name, cmbPrinters.SelectedItem.ToString()))
' Get a print ticket with modified print options for the selected printer.
Dim printTicket As PrintTicket = GetPrintTicket(selectedPrintQueue)
' Send the XPS document to the selected printer.
PrintXpsDocumentAsync(txtXpsFilePath.Text, selectedPrintQueue, printTicket)
' Show modified print options.
Dim optionList As List(Of String) = New List(Of String)()
If printTicket.Collation = Collation.Collated Then optionList.Add("Collated")
If printTicket.Duplexing = Duplexing.TwoSidedLongEdge Then optionList.Add("TwoSidedLongEdge")
If printTicket.Stapling = Stapling.StapleDualLeft Then optionList.Add("StapleDualLeft")
Dim options = If(optionList.Count > 0, String.Join(", ", optionList), "None")
' Show result message.
MessageBox.Show($"Sent {Path.GetFileName(txtXpsFilePath.Text)} to the printer.{vbCrLf}Print options: {options}")
End Sub
' <GetPrintQueues>
''' <summary>
''' Return a collection of print queues, which individually hold the features or states
''' of a printer as well as common properties for all print queues.
''' </summary>
''' <returns>A collection of print queues.</returns>
Public Shared Function GetPrintQueues() As PrintQueueCollection
' Create a LocalPrintServer instance, which represents
' the print server for the local computer.
Dim localPrintServer As LocalPrintServer = New LocalPrintServer()
' Get the default print queue on the local computer.
'Dim printQueue As PrintQueue = localPrintServer.DefaultPrintQueue
' Get all print queues on the local computer.
Dim printQueueCollection As PrintQueueCollection = localPrintServer.GetPrintQueues()
' Return a collection of print queues, which individually hold the features or states
' of a printer as well as common properties for all print queues.
Return printQueueCollection
End Function
' </GetPrintQueues>
' <GetPrintTicket>
''' <summary>
''' Returns a print ticket, which is a set of instructions telling a printer how
''' to set its various features, such as duplexing, collating, and stapling.
''' </summary>
''' <param name="printQueue">The print queue to print to.</param>
''' <returns>A print ticket.</returns>
Public Shared Function GetPrintTicket(printQueue As PrintQueue) As PrintTicket
Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()
' Get a default print ticket from printer.
Dim printTicket As PrintTicket = printQueue.DefaultPrintTicket
' Modify the print ticket.
If printCapabilites.CollationCapability.Contains(Collation.Collated) Then
printTicket.Collation = Collation.Collated
End If
If printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
printTicket.Duplexing = Duplexing.TwoSidedLongEdge
End If
If printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
printTicket.Stapling = Stapling.StapleDualLeft
End If
' Returns a print ticket, which is a set of instructions telling a printer how
' to set its various features, such as duplexing, collating, and stapling.
Return printTicket
End Function
' </GetPrintTicket>
' <PrintXpsDocument>
''' <summary>
''' Asynchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocumentAsync(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)
' Create an XpsDocumentWriter object for the print queue.
Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)
' Open the selected document.
Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Asynchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket)
End Sub
''' <summary>
''' Synchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocument(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)
' Create an XpsDocumentWriter object for the print queue.
Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)
' Open the selected document.
Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Synchronously, add the XPS document together with a print ticket to the print queue.
xpsDocumentWriter.Write(fixedDocSeq, printTicket)
End Sub
' </PrintXpsDocument>
End Class
End Namespace
+14
View File
@@ -47,6 +47,20 @@ items:
href: controls/how-to-create-apply-style.md href: controls/how-to-create-apply-style.md
- name: Create and apply a template - name: Create and apply a template
href: controls/how-to-create-apply-template.md href: controls/how-to-create-apply-template.md
- name: Documents & Printing
items:
- name: Printing
expanded: true
items:
- name: Overview
href: documents/printing-overview.md
- name: Common tasks
items:
- name: Display the print dialog
href: documents/how-to-display-print-dialog.md
- name: Programmatically print XPS files
href: documents/how-to-print-xps-files.md
- name: Data binding - name: Data binding
items: items:
- name: Overview - name: Overview
+18 -1
View File
@@ -301,6 +301,23 @@
"TargetUrl": "/dotnet/desktop/wpf/data/binding-declarations-overview?view=netdesktop-5.0#binding-direction" "TargetUrl": "/dotnet/desktop/wpf/data/binding-declarations-overview?view=netdesktop-5.0#binding-direction"
}, },
// Documents/Printing
{
"Redirect": "TwoWay",
"SourceUrl": "/dotnet/desktop/wpf/advanced/printing-overview?view=netframeworkdesktop-4.8",
"TargetUrl": "/dotnet/desktop/wpf/documents/printing-overview?view=netdesktop-5.0"
},
{
"Redirect": "TwoWay",
"SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-invoke-a-print-dialog?view=netframeworkdesktop-4.8",
"TargetUrl": "/dotnet/desktop/wpf/documents/how-to-display-print-dialog?view=netdesktop-5.0"
},
{
"Redirect": "TwoWay",
"SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-programmatically-print-xps-files?view=netframeworkdesktop-4.8",
"TargetUrl": "/dotnet/desktop/wpf/documents/how-to-print-xps-files?view=netdesktop-5.0"
},
// Systems - XAML // Systems - XAML
{ {
"Redirect": "TwoWay", "Redirect": "TwoWay",
@@ -363,7 +380,7 @@
//}, //},
// ======== // ========
// WPF 3.1 -> 5/6 // WPF Core -> 5/6
// ======== // ========
{ {
"Redirect": "OneWay", "Redirect": "OneWay",