locked
XPS Printing of an Adorner RRS feed

  • Question

  • Hoping someone can help me with this,
    Im trying to print a canvas I have to an XPS document which i'm then sending to a printer...

    I have Paths and Ellipses on the canvas and the Paths have an adorner on the end of them.
    Problem is when I send the canvas to the XpsDocumentWriter I get everything except the adorned part of the path.
    If i change the writer to a batchwriter and print ONE of the AdornedLayers on the path seperately i get my original page and then an additional page just containing all the adorned layers.

    I tried adding the adorned layers to the canvas but their already contained within the path so of course it didnt allow that.
    I think I have to use a FlowWriter perhaps instead of a FixedDocumentSequence but in a FlowWriter there doesnt seem to be a DocumentPaginator...

    So im a bit stuck..
    Thanks in advance for any help!!

    Friday, February 15, 2008 4:02 AM

Answers

  • This works pretty well for me:

    Code Snippet
    <Window x:Class="AnswerHarness.PrintAtLandscape"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="PrintAtLandscape" Height="500" Width="600">
    <
    Window.Resources>
    <
    Style TargetType="{x:Type ContentControl}">
    <
    Setter Property="Template">
    <
    Setter.Value>
    <
    ControlTemplate TargetType="{x:Type ContentControl}">
    <
    AdornerDecorator>
    <
    ContentPresenter
    Content="{TemplateBinding Content}"
    ContentTemplate="{TemplateBinding ContentTemplate}" />
    </
    AdornerDecorator>
    </
    ControlTemplate>
    </
    Setter.Value>
    </
    Setter>
    </
    Style>
    </
    Window.Resources>
    <
    StackPanel>
    <
    ContentControl x:Name="container" Width="400" Height="300" Margin="5">
    <
    Canvas>
    <
    Ellipse x:Name="ellipse" Width="300" Height="200" Fill="Red" Canvas.Left="20" Canvas.Right="20"/>
    </
    Canvas>
    </
    ContentControl>
    <
    Button Width="120" Height="30" Content="Print" Name="printButton" />
    </
    StackPanel>
    </
    Window>

    public partial class
    PrintAtLandscape : Window
    {
    public PrintAtLandscape()
    {
    InitializeComponent();
    ellipse.Loaded += delegate
    {
    AdornerLayer al = AdornerLayer.GetAdornerLayer(ellipse);
    if (al != null)
    {
    al.Add(new ResizingAdorner(ellipse));
    }
    };
    printButton.Click += delegate
    {
    LocalPrintServer ps = new LocalPrintServer();
    PrintQueue pq = ps.DefaultPrintQueue;
    XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
    PrintTicket pt = pq.UserPrintTicket;
    if (xpsdw != null)
    {
    pt.PageOrientation = PageOrientation.Portrait;
    PageMediaSize pageMediaSize = new PageMediaSize(this.ActualWidth, this.ActualHeight);
    pt.PageMediaSize = pageMediaSize;
    xpsdw.Write(container);
    }
    };
    }
    }


    The trick here is to place AdornerDecorator into the ContentControl's template, and print the containing ContentControl instead, in this way you can get the adorner visuals in the print output.

    Hope this helps

    Monday, February 18, 2008 6:57 AM

All replies

  • This works pretty well for me:

    Code Snippet
    <Window x:Class="AnswerHarness.PrintAtLandscape"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="PrintAtLandscape" Height="500" Width="600">
    <
    Window.Resources>
    <
    Style TargetType="{x:Type ContentControl}">
    <
    Setter Property="Template">
    <
    Setter.Value>
    <
    ControlTemplate TargetType="{x:Type ContentControl}">
    <
    AdornerDecorator>
    <
    ContentPresenter
    Content="{TemplateBinding Content}"
    ContentTemplate="{TemplateBinding ContentTemplate}" />
    </
    AdornerDecorator>
    </
    ControlTemplate>
    </
    Setter.Value>
    </
    Setter>
    </
    Style>
    </
    Window.Resources>
    <
    StackPanel>
    <
    ContentControl x:Name="container" Width="400" Height="300" Margin="5">
    <
    Canvas>
    <
    Ellipse x:Name="ellipse" Width="300" Height="200" Fill="Red" Canvas.Left="20" Canvas.Right="20"/>
    </
    Canvas>
    </
    ContentControl>
    <
    Button Width="120" Height="30" Content="Print" Name="printButton" />
    </
    StackPanel>
    </
    Window>

    public partial class
    PrintAtLandscape : Window
    {
    public PrintAtLandscape()
    {
    InitializeComponent();
    ellipse.Loaded += delegate
    {
    AdornerLayer al = AdornerLayer.GetAdornerLayer(ellipse);
    if (al != null)
    {
    al.Add(new ResizingAdorner(ellipse));
    }
    };
    printButton.Click += delegate
    {
    LocalPrintServer ps = new LocalPrintServer();
    PrintQueue pq = ps.DefaultPrintQueue;
    XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
    PrintTicket pt = pq.UserPrintTicket;
    if (xpsdw != null)
    {
    pt.PageOrientation = PageOrientation.Portrait;
    PageMediaSize pageMediaSize = new PageMediaSize(this.ActualWidth, this.ActualHeight);
    pt.PageMediaSize = pageMediaSize;
    xpsdw.Write(container);
    }
    };
    }
    }


    The trick here is to place AdornerDecorator into the ContentControl's template, and print the containing ContentControl instead, in this way you can get the adorner visuals in the print output.

    Hope this helps

    Monday, February 18, 2008 6:57 AM
  •  

    Thank you! This has been SUCH A BIG HELP!
    Tuesday, May 27, 2008 1:15 AM
  • Whewwwww.....I have been searching the web for the past 5 hours looking for an easy way to print an XPS FixedPage document...and Marco yours is the first solution that "just works" and is relatively simple.  I'm convinced that XPS printing is not an easy or trivial task...way too much do this and pass to that which passes to something else before you get anywhere close a printer...

    I understand that WPF has the printvisual...but that doesn't help you print in memory objects that aren't visually displayed yet... :-(

    So....a big thank you Marco!!! 

    Cheers,
    JKnapp
    Tuesday, November 11, 2008 7:41 AM
  • I used the code above and I got this problem: this code only prints the content that is visible on the screen, not the whole content of the Editor.

    how Can I print the whole content not the visible part only?

    • Proposed as answer by raym0ndish Wednesday, August 3, 2011 7:21 PM
    Wednesday, August 3, 2011 6:58 PM