Hi, @Jane Jie Chen. Welcome to Microsoft Q&A.
You could refer to the following methods to achieve the effect you want.
Its core: You could get a VisualBrush
through new VisualBrush(paginator.GetPage(pageNumber).Visual)
, which could be bound to <Rectangle Fill="{Binding VisualBrush}"></Rectangle>
for display and printing.
Create a window to select which pages to print (1. Red border represents selection 2. Click to cancel or select).
PreviewResultWindow.xaml
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Visible" >
<ItemsControl x:Name="PreViewDataControl" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="10" Width="200" Height="150" Click="Button_Click">
<Button.Content>
<Rectangle Width="200" Height="150" Fill="{Binding PageVisualBrush}"></Rectangle>
</Button.Content>
<Button.Style>
<Style TargetType="Button">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<!-- Triggered by the check property of DataContext -->
<DataTrigger Binding="{Binding Check}" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Button Grid.Column="1" Content="Confirm" Height="70" Click="Button_Click_1"></Button>
</Grid>
PreviewResultWindow.xaml.cs
public partial class PreviewResultWindow : Window
{
public PreviewResultWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var previewDocument = ((sender as Button).DataContext as PreViewDocument);
previewDocument.Check = !previewDocument.Check;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.Close();
}
}
Provide binding data for PreviewResultWindow.xaml
.
PreViewDocument.cs
public class PreViewDocument : INotifyPropertyChanged
{
private VisualBrush pageVisualBrush;
public VisualBrush PageVisualBrush { get { return pageVisualBrush; } set { pageVisualBrush = value; OnPropertyChanged(nameof(PageVisualBrush)); } }
public bool check;
public bool Check { get { return check; } set { check = value; OnPropertyChanged(nameof(Check)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml
<Grid x:Name="MyGrid" Loaded="OnLoaded">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="6*"/>
</Grid.RowDefinitions>
<Button Content="Print" Click="PrintButtonClick" Margin="10" HorizontalAlignment="Left" Width="75"></Button>
<DocumentViewer x:Name="viewer" Grid.Row="1"/>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private FixedDocument _fixedDocument;
public MainWindow()
{
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Load the FixedDocument
var document = new XpsDocument("InputFile.xps", FileAccess.Read);
var sequence = document.GetFixedDocumentSequence();
_fixedDocument = sequence.References[0].GetDocument(false);
// Assign it to the viewer
viewer.Document = _fixedDocument.DocumentPaginator.Source;
}
private async Task PrintReport()
{
PrintDialog printDialog = new PrintDialog();
printDialog.UserPageRangeEnabled = true;
if (printDialog.ShowDialog() == false)
return;
//-----------------Solution 1: Print without using PageRangeDocumentPaginator.cs--------------------------
DocumentPaginator paginator = _fixedDocument.DocumentPaginator;
ObservableCollection<PreViewDocument> previewDocuments = new ObservableCollection<PreViewDocument>();
//Pre-print results
//Select All
for (int pageNumber = 0; pageNumber <= paginator.PageCount - 1; pageNumber++)
{
var previewDocument = new PreViewDocument() { PageVisualBrush = new VisualBrush(paginator.GetPage(pageNumber).Visual), Check = true };
previewDocuments.Add(previewDocument);
}
//Range selection
if (printDialog.PageRangeSelection == PageRangeSelection.UserPages)
{
for (int pageNumber = 0; pageNumber < paginator.PageCount; pageNumber++)
{
if (pageNumber >= Convert.ToInt32(printDialog.PageRange.PageFrom) - 1 && pageNumber <= Convert.ToInt32(printDialog.PageRange.PageTo) - 1)
{
continue;
}
previewDocuments[pageNumber].Check = false;
}
}
ConfirmPrintData(previewDocuments);
var visualBrushs = previewDocuments.Where(p => p.Check == true).Select(p => p.PageVisualBrush).ToList();
ExecutePrint(printDialog, visualBrushs);
//--------------------Solution 2: Print using PageRangeDocumentPaginator.cs-----------------------------
//if (printDialog.PageRangeSelection == PageRangeSelection.UserPages)
//{
// DocumentPaginator paginator = new PageRangeDocumentPaginator(_fixedDocument.DocumentPaginator, printDialog.PageRange);
// ObservableCollection<PreViewDocument> previewDocuments = new ObservableCollection<PreViewDocument>();
// for (int pageNumber = Convert.ToInt32(printDialog.PageRange.PageFrom); pageNumber <= Convert.ToInt32(printDialog.PageRange.PageTo); pageNumber++)
// {
// var previewDocument = new PreViewDocument() { PageVisualBrush = new VisualBrush(paginator.GetPage(pageNumber).Visual), Check = true };
// previewDocuments.Add(previewDocument);
// }
// ConfirmPrintData(previewDocuments);
// var visualBrushs = previewDocuments.Where(p => p.Check == true).Select(p => p.PageVisualBrush).ToList();
// ExecutePrint(printDialog, visualBrushs);
//}
//else
//{
// printDialog.PrintDocument(_fixedDocument.DocumentPaginator, "PrintReport");
//}
MessageBox.Show("Printing completed");
}
public void ConfirmPrintData(ObservableCollection<PreViewDocument> previewDocuments)
{
PreviewResultWindow previewResultWindow = new PreviewResultWindow();
previewResultWindow.PreViewDataControl.ItemsSource = previewDocuments;
previewResultWindow.ShowDialog();
}
private async void PrintButtonClick(object sender, RoutedEventArgs e)
{
await PrintReport();
}
public void ExecutePrint(PrintDialog printDialog,List<VisualBrush> visualBrushes)
{
FixedDocument fixedDocument = new FixedDocument();
foreach (var visualBrush in visualBrushes)
{
FixedPage page = new FixedPage();
page.Width = printDialog.PrintableAreaWidth;
page.Height = printDialog.PrintableAreaHeight;
// VisualBrush as rectangle content
Rectangle rect = new Rectangle
{
Width = page.Width,
Height = page.Height,
Fill = visualBrush
};
// Add to FixedPage
page.Children.Add(rect);
// Adding PageContent to FixedDocument
PageContent pageContent = new PageContent();
((IAddChild)pageContent).AddChild(page);
fixedDocument.Pages.Add(pageContent);
}
// Printing FixedDocument
printDialog.PrintDocument(fixedDocument.DocumentPaginator, "Print Report");
}
}
In the above code, VisualBrush
uses ExecutePrint()
to print; VisualBrush
uses ConfirmPrintData()
to open the PreviewResultWindow.xaml
dialog box to display data and let the user select the print result. You could adjust the PreviewResultWindow
according to your own preferences to make the selection in a certain way.
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.