Print FixedDocument programmatically - wpf

I am using a WPF FixedDocument with databinding for a simple invoice report. Works perfect when viewed inside the sofware itsself.
But i want to print a series of invoices in one click. The following code works perfect (quick 'n dirty, just loads an invoice one by one directly inside the viewmodel, for testing purposes) when I choose the XPS writer, bu fails to print correctly when printing to a real printer. I can see nothing of the data bound to the report. All the graphical elements such as lines are there, but no data. (When i print, with the same button, to de xps writer printer, all data is present, and correct...)
Any Ideas?
private void ExecutePrintCommand(object sender, ExecutedRoutedEventArgs args)
{
var invs = args.Parameter as IList<object>;
using (CompuDataContext db = new CompuDataContext())
{
DataLoadOptions dl = new DataLoadOptions();
dl.LoadWith<Invoice>(f => f.Invoicelines);
db.LoadOptions = dl;
ReportViewer viewer = new ReportViewer();
PrintDialog dlg = new PrintDialog();
if (dlg.ShowDialog() == true)
{
PrintQueue q = dlg.PrintQueue;
foreach (var o in invs)
{
InvoiceListDisplay inv = o as InvoiceListDisplay;
Invoice invoice = db.Invoices.Single(f => f.Id == inv.Id);
viewer.DataContext = new InvoicePrintViewModel(invoice);
XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(q);
xpsdw.Write(viewer.Document);
}
}
}
}

mmkay, so I found the answer myself here :)
This helped me (Anybody an idea what the 'reason' behind is? Bug?)
PS: In a flowdocument, i experience the same issue, and have not been able to resolve it there. Any ideas?

Related

How to remove/disable the print button from the DocumentViewer in code (when on its own thread)?

I am running the following code in a background thread as an STA apartment to provide a Print Preview in a document viewer:
// Print Preview
public static void PrintPreview(FixedDocument fixeddocument)
{
MemoryStream ms = new MemoryStream();
using (Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite))
{
Uri u = new Uri("pack://TemporaryPackageUri.xps");
PackageStore.AddPackage(u, p);
XpsDocument doc = new XpsDocument(p, CompressionOption.Maximum, u.AbsoluteUri);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
writer.Write(fixeddocument.DocumentPaginator);
var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;
THIS FAILS ---> docViewer.CommandBindings.Remove(???Print Button???);
FixedDocumentSequence fixedDocumentSequence = doc.GetFixedDocumentSequence();
docViewer.Document = fixedDocumentSequence as IDocumentPaginatorSource;
previewWindow.ShowDialog();
PackageStore.RemovePackage(u);
doc.Close();
}
}
All works well. However, since this is running in its own thread--not the main thread--the print dialogue on the Document Viewer crashes.
In code, how can I remove and/or disable the Print button from the DocumentViewer?? (I have read everything I could find in Google, and it all is in XAML, not very helpful).
Any help is much appreciated. TIA
Update#1: The only way I can see to do this, is to drop the Print Button from the control template and use a custom Document Viewer. A workable style is given at Document Viewer Style.
It still would be nice if I could simply remove the button from the system Document viewer?
Using the method from this answer, you can alter the visibility of the PrintButton programmatically like this. Let's say I put the method in a class called UIElementHelper:
var button = UIElementHelper.FindChild<Button>(docViewer, "PrintButton");
button.Visibility = Visibility.Collapsed;

Telerik Reports parameters from WindowsForm Codebehind to Report

I'm working on a Windows Forms Application where I want to load Reports into a Reportviewer after a click on a Button.
This is the Event that gets triggered by pressing on the button in the Code behind of the Windows Form:
private void button1_Click(object sender, EventArgs e)
{
Telerik.Reporting.InstanceReportSource reportSource = new
Telerik.Reporting.InstanceReportSource();
reportSource.ReportDocument = new Reportlibrary.Report1();
reportSource.Parameters.Add(new Telerik.Reporting.Parameter("OrderNumber","123456789"));
reportViewer1.ReportSource = reportSource;
reportViewer1.RefreshReport();
}
The problem now is that I have no Idea how I can access / get the parameter I added before Refreshing the Reportviewer.
The Report already has set a Datasource. I don't know if this matters.
This is what I have right now. I've tried everything and I'm just not getting further.
public Report1()
{
InitializeComponent();
Position[] all = new Position[]{
new Position("Test", "Test","test"),
};
this.DataSource = all;
MessageBox.Show("Number: " +
this.Report.ReportParameters["OrderNumber"].Value.ToString());
}
Is there any way to get this parameter straight after InitializeComponent(); ?
Do I need to add another Event to the report to access it? If yes which on is the best way to do this?
Any help very apreciated.
Thank you
Set the parameters of the report on an instance of the report itself (not the report source), such as:
TopPageViews report = new TopPageViews();
report.ReportParameters["StartDate"].Value = new DateTime(2013, 3, 1);
report.ReportParameters["EndDate"].Value = new DateTime(2013, 3, 1);
InstanceReportSource reportSource = new InstanceReportSource();
reportSource.ReportDocument = report;
this.reportViewer1.ReportSource = reportSource;
this.reportViewer1.RefreshReport();
In your report constructor, after InitializeComponent, subscribe a handler to the ItemDataBinding event:
this.ItemDataBinding += TopPageViews_ItemDataBinding;
And in your handler, you can obtain the value as you normally would:
DateTime startDateParm = (DateTime)this.ReportParameters["StartDate"].Value;
You can use the debugger to see the value.
i know its an old question but after experiencing the same issue this how i did it and passed two parameter of date.
private void button1_Click(object sender, EventArgs e)
{
Report2 report = new Report2();
report.ReportParameters["datefrom"].Value
=dateTimePicker1.Value;
report.ReportParameters["dateto"].Value = dateTimePicker2.Value;
var rSource = new InstanceReportSource();
rSource.ReportDocument = report;
reportViewer1.ReportSource = rSource;
reportViewer1.RefreshReport();
}

Windows Forms Webbrowser Full history

I just want to show the full History of a WinForms.Webbrowser,
I know how to navigate forward and backward with
webBrowser1.Document.Window.History.Go/Back/Forward(1)
I just want to know how to visualize the History object, e.g in a DataGridView
DataGridView dgvChronic = new DataGridView();
dgvChronic.DataSource = webBrowser1.Document.Window.History;
but this doesn't work :/
I want to do something like this (pseudocode):
foreach (Link lk in webBrowser1.Document.Window.History)
{
dgvChronic.Rows.Add(lk, "blabla");
}
My Solution:
private List<object> chronic = new List<object>();
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
//Chronic hier erstellen
if (tsURL.Text != webBrowser1.Url.ToString())
{
tsURL.Text = webBrowser1.Url.ToString();
List<string> website = new List<string>();
website.Add(DateTime.Now.ToString());
website.Add(tsURL.Text);
chronic.Add(website);
}
}
Then to visualize the History:
foreach (List<string> website in chronic)
{
dgvChronic.Rows.Add(website[0], website[1]);
}
ill mark trippinos Answer as accepted because its almost the same (i haven't tested it but it looks like it will work, too)
It seems to be unsupported, but there is a quite simple workaround that requires few lines.
Take a look at this thread:
msdn webbrowser thread
Hope this helps.
DataGridView.DataSource does not support WebBrowser Hisory type.
You should add each navigated URL to a DataTable and set this table to data source of DataGridView.

Start and Back Button pressed in rapid succession WP7

I asked this question in a similar post but there have been significant updates since then, but still no results so I will try to re-ask the question with the updated information.
Basically I have a pivot view with 4 pivot items. If I create the scenario where I hit the windows key then rapidly press the back key my application will reopen without reconstructing (this is the expected outcome). The functionality of the application is there. I can press application bar buttons etc.
What doesn't work is the pivot items are frozen. If I was on Pivot item A and I press the start and back button quickly I come back to Pivot Item A. If I try to switch Pivot Items, the screen does not update, its "frozen" on Pivot Item A BUT the functionality of Pivot Item B is there. (I know this because the application bar Icons for Pivot Item B are now showing).
I have read many articles on proper tombstoning scenarios and how to approach this problem. My data IS being tombstoned correctly, and upon reactivation the tombstoned data works. No objects are null so I don't have any exceptions being thrown at me.
I check to see if I need to reload the Main ViewModel (I don't need to in this case so the UI elements being created initially are not being re created).
What does fix the problem however is if the application is reconstructed. Lets say I go to the marketplace from my app, let it finish loading and press back, My application will be refreshed and working fine since it properly deactivated and reconstructed istelf. I don't rely on constructors doing all the work so I am not missing any key elements not being set when they aren't fired in the windows/back button scenario.
Does anyone have any idea why my screen would not be updating?
constructor/loaded event/on navigated to event
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (App.firstTimeLoading == true)
{
App.firstTimeLoading = false;
}
BuildApplicationBar();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = App.ViewModel;
App.viewIdentifier = StringResource.MainPageView;
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
String bookTitle;
App.Parser.appBookInfoDict.TryGetValue(CPlayerInventoryKeys.kInventoryKeyTitleShortTitle, out bookTitle);
PivotBackground.Title = bookTitle.ToUpper();
CreatePivotItems();
}
if (App.playerController.chapterPlayer.Source == null)
App.restoreStateClass.RestoreState();
//applies the proper background image
if (App.isDarkTheme)
{
BitmapImage bitmapImage = new BitmapImage(new Uri(StringResource.PanoramaBlackImage, UriKind.Relative));
BackgroundImage.ImageSource = bitmapImage;
BackgroundImage.Opacity = .85;
}
else
{
BitmapImage bitmapImage = new BitmapImage(new Uri(StringResource.PanoramaWhiteImage, UriKind.Relative));
BackgroundImage.ImageSource = bitmapImage;
BackgroundImage.Opacity = .5;
}
if (App.firstTimeLoading == false && PivotBackground.SelectedItem != SuggestedPivotItem)
BuildApplicationBar();
else if (PivotBackground.SelectedItem == SuggestedPivotItem)
{
BuildMarketPlaceApplicationBar();
}
base.OnNavigatedTo(e);
}
I found the answer. Since I had a media element open (play/paused) and I was implementing the "non tombstoned" method of hitting windows key and back button very quickly, the media element source was corrupt. Even though I reset this source, apparently it can be ignored and not function properly. All I had to do was add a line of code to the Application Deactivated handler.
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
App.MainAudioPlayer.Source = null; //(only showing line added)
}
The behavior you are describing seems to be solely related to the way you are manipulating data internally and constructing your layout. I tested this both in the emulator and on a couple of physical devices, both producing normal output (even when bound to a view model).
Try creating a new Pivot-based application (without all your data - just using the default template) and see if the problem persists. Also worth mentioning - are you testing on a device or in the emulator?
Are you using transitions from the toolkit?
Are they defined in XAML?
If so that could be the issue. There's a bug which is fixed in the next version.
The solution for now is to remove the transitions or define them in code.

WPF printing of multiple pages with preview

The more I read about the subject the less I understand so apologies in advance if the below seems completely off the wall.
I have a usercontrol that contains a flowdocument - a view with a corresponding viewmodel. The aim is to send this to a preview window where the user can view the document and also print it.
I lifted some code from an example at http://www.eggheadcafe.com/tutorials/aspnet/9cbb4841-8677-49e9-a3a8-46031e699b2e/wpf-printing-and-print-pr.aspx
When the below is called
Public Shared Sub PrintPreview(owner As Window, data As FormData)
Using xpsStream As New MemoryStream()
Using package__1 As Package = Package.Open(xpsStream, FileMode.Create, FileAccess.ReadWrite)
Dim packageUriString As String = "memorystream://data.xps"
Dim packageUri As New Uri(packageUriString)
PackageStore.AddPackage(packageUri, package__1)
Dim xpsDocument__2 As New XpsDocument(package__1, CompressionOption.Maximum, packageUriString)
Dim writer As XpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument__2)
Dim visual As New Form(data)
Dim printTicket As New PrintTicket()
printTicket.PageMediaSize = A4PaperSize
writer.Write(visual, printTicket)
Dim document As FixedDocumentSequence = xpsDocument__2.GetFixedDocumentSequence()
xpsDocument__2.Close()
Dim printPreviewWnd As New PrintPreviewWindow(document)
printPreviewWnd.Owner = owner
printPreviewWnd.ShowDialog()
PackageStore.RemovePackage(packageUri)
End Using
End Using
This brings up the print preview window and shows the user control that holds the flowdocument. However, it only shows the first of what should be multiple pages. I was under the assumption the whole point of writing the xps and then reading it back again in this window was to work around the problem of printing a visual but I'm obviously misunderstanding the whole process. Any help in getting through my thick head what I need to do to be able to view all of the pages in the document would be much appreciated.
Cheers
I thought the above with using xpsdocument and getfixeddocumentsequence would convert the flowdocument to a fixeddocument but seeing it doesn't, am I perhaps writing it wrongly??
You can print a visual to an XPS. However, as I understand it, it is your job to manage pages. If your visual is too big to fit on a page, you need to find a way to split it onto multiple pages.
The source code I posted here prints a list of items over many pages:
https://bitbucket.org/paulstovell/samples/src/a323f0c65ea4/XPS%20Report%20Generator/
If you can find a way to split your visuals (perhaps create 3 forms, with 15 items per form) into pages, you can then use this:
using (var doc = new XpsDocument("P:\\Test2.xps", FileAccess.Write))
{
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
var collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
collator.Write(form1);
collator.Write(form2);
collator.Write(form3);
collator.EndBatchWrite();
}
var doc2 = new XpsDocument("P:\\Test2.xps", FileAccess.Read);
var seq = doc2.GetFixedDocumentSequence();
var window = new Window();
window.Content = new DocumentViewer {Document = seq};
window.ShowDialog();
Also, note that if you're newing up a visual and printing it, you'll need to size it first, otherwise you may get an empty screen. Here's an example of generating a page of data (of course you'd change the sizes to fit an A4 sheet).
private StackPanel CreatePage()
{
var panel = new StackPanel();
panel.Width = 1000;
panel.Height = 1000;
for (var i = 0; i < 10; i++)
{
panel.Children.Add(new TextBlock() {Text = "Item " + i});
}
panel.Measure(new Size(1000, 1000));
panel.Arrange(new Rect(0, 0, 1000, 1000));
return panel;
}

Resources