Hi,
I'm generating XPS reports in a non-WPF application. Sometimes, the bound data is not rendered in the report and I cannot understand why.The GUI is correctly rendered, but XPS is not. I have searched the net for days. It seems at least a few others are experiencing the
same problem. Let's create a sample project that demonstrates the problem! Please note that I cannot print the Visual directly since the printing function may be used in a service or similar.
1) Create a WPF project called WpfApplication1.
2) Replace the MainWindow class with the code below.
3) Add a my_template.xaml file to the solution and change its Build Action to "None".
4) Add the my_template.xaml file (code below) to the application's resources (Resources.resx).
5) Add references to ReachFramework and System.Printing.
6) Run the application! The GUI shows the text "test", but the generated XPS document (saved on your Desktop) does not!
Note the trace window. This is the last trace after the dispatcher has updated the bindings:
System.Windows.Data Warning: 89 : BindingExpression (hash=8761922): TransferValue -using final value 'test'
What is going on?!
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = "test";
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var documents = new List<FixedDocument>();
var document = XamlReader.Parse(WpfApplication1.Properties.Resources.my_template) as FixedDocument;
InjectData(document, DataContext);
documents.Add(document);
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = System.IO.Path.Combine(path, "XpsTest.xps");
using (var stream = File.Create(filename))
{
ConvertToXps(documents, stream);
}
foreach (var fixedPage in document.Pages.Select(pageContent => pageContent.Child))
{
fixedPage.Children.Clear();
}
}
protected void InjectData(FixedDocument document, object dataSource)
{
document.DataContext = new { MyTextData = dataSource };
// we need to give the binding infrastructure a push as we
// are operating outside of the intended use of WPF
var dispatcher = Dispatcher.CurrentDispatcher;
dispatcher.Invoke(
DispatcherPriority.SystemIdle,
new DispatcherOperationCallback(delegate { return null; }),
null);
}
protected void ConvertToXps(IEnumerable<FixedDocument> fixedDocuments, Stream outputStream)
{
var package = Package.Open(outputStream, FileMode.Create);
var xpsDoc = new XpsDocument(package, CompressionOption.Normal);
var xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
// XPS documents are built using fixed document sequences.
var fixedDocSeq = new FixedDocumentSequence();
foreach (var fixedDocument in fixedDocuments)
{
var docRef = new DocumentReference();
docRef.BeginInit();
docRef.SetDocument(fixedDocument);
docRef.EndInit();
((IAddChild)fixedDocSeq).AddChild(docRef);
}
// Write out our fixed document to XPS.
xpsWriter.Write(fixedDocSeq.DocumentPaginator);
xpsDoc.Close();
package.Close();
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Window_Loaded"
Title="MainWindow"
Width="793.92" Height="1122.24" Margin="100"><Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="200"><TextBlock Background="LightGray" Text="{Binding}"
FontSize="36"/></Grid></Window>
my_template.xaml
<FixedDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><PageContent><FixedPage Width="793.92" Height="1122.24" Margin="100"><Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="200"><TextBlock Background="LightGray" Text="{Binding MyTextData,PresentationTraceSources.TraceLevel=High}"
FontSize="36"/></Grid></FixedPage></PageContent></FixedDocument>