Printing a stackpanel containing a listbox over multiple pages wpf - c#

Hi I am looking to print a StackPanel that contains a listbox which can contain an infinite number of items and therefore needs to print over multiple pages. I found this code online and it works fine.
public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
{
if (printDialog == null)
{
printDialog = new PrintDialog();
}
var capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
var pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
var visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
var fixedDoc = new FixedDocument();
//If the toPrint visual is not displayed on screen we neeed to measure and arrange it
toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
//
var size = toPrint.DesiredSize;
//Will assume for simplicity the control fits horizontally on the page
double yOffset = 0;
while (yOffset < size.Height)
{
var vb = new VisualBrush(toPrint)
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
ViewboxUnits = BrushMappingMode.Absolute,
TileMode = TileMode.None,
Viewbox = new Rect(0, yOffset, visibleSize.Width, visibleSize.Height)
};
var pageContent = new PageContent();
var page = new FixedPage();
((IAddChild)pageContent).AddChild(page);
fixedDoc.Pages.Add(pageContent);
page.Width = pageSize.Width;
page.Height = pageSize.Height;
var canvas = new Canvas();
FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
canvas.Width = visibleSize.Width;
canvas.Height = visibleSize.Height;
canvas.Background = vb;
page.Children.Add(canvas);
yOffset += visibleSize.Height;
}
return fixedDoc;
}
However this causes certain items of a listbox to be cut off at the bottom of a page and continued on the next page (as shown below). Is it possible to modify this code in any way to determine the size of the page and if the current listboxitem does not fit onto this page that it starts on the next page? Quite new to all this so any help would be greatly appreciated.

I had a similiar task once and came up with this code, which uses a 'dummy' renderer to determine the height of the element up front and then either adds it to the current page or creates a new one. For sure, that's not a very beautiful solution, but it did the job at the time. Maybe you can take sth. away from it.
Size A4Size = new Size(793.92, 1122.24);
Size InfiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
var pages = new List<FrameworkElement>();
int pageNumber = 0;
var printDate = DateTime.Now;
var size = A4Size;
var currentPage = new Report(size, printDate);
currentPage.Render();
var listElements = new Queue<ElementsToPrint>(...);
var dummyRenderer = new Viewbox();
dummyRenderer.Child = currentPage;
dummyRenderer.Measure(InfiniteSize);
dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
dummyRenderer.UpdateLayout();
var template = (DataTemplate)View.FindResource("ItemTemplate");
dummyRenderer.Child = null;
var availableHeight = currentPage.View.ActualHeight;
while (listElements.Count > 0)
{
var elementToRender = listElements.Dequeue();
dummyRenderer.Child = new ListViewItem()
{
Content = elementToRender,
ContentTemplate = template,
Foreground = Brushes.Black
};
dummyRenderer.Measure(InfiniteSize);
dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
dummyRenderer.UpdateLayout();
var renderedItem = (ListViewItem)dummyRenderer.Child;
dummyRenderer.Child = null;
var willItFit = availableHeight > renderedItem.ActualHeight;
if (willItFit)
{
currentPage.DataListView.Items.Add(renderedItem);
availableHeight -= renderedItem.ActualHeight;
}
else
{
dummyRenderer.Child = currentPage;
dummyRenderer.Measure(InfiniteSize);
dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
dummyRenderer.UpdateLayout();
dummyRenderer.Child = null;
pages.Add(currentPage);
// Set up a new Page
pageNumber++;
currentPage = new DiaryReport(size,pageNumber,printDate,anonymous);
dummyRenderer.Child = currentPage;
dummyRenderer.Measure(InfiniteSize);
dummyRenderer.Arrange(new Rect(dummyRenderer.DesiredSize));
dummyRenderer.UpdateLayout();
dummyRenderer.Child = null;
availableHeight = currentPage.DataListView.ActualHeight;
currentPage.DataListView.Items.Add(renderedItem);
availableHeight -= renderedItem.ActualHeight;
}

Related

Zoom Image using WPF MVVM, will move the top layer controls. How can it be fixed on image zoom time?

Currently i am working on image processing project, where i have one review screen in which i set the image on image container, and on top of the image, all four corners has meta data, which are fixed. Means while i zoom in/out the image, the top content will remain at the fixed position not move. This is my requirement.
Now i have set all content dynamically using the stack panel and all meta data will stay on fixed position except the bottom right position, which will be moved while image is zoomed in/out.
below is the reference screen shot where red mark shows the metadata will moved and hide at right side.
Here is the code for bottom right content
public async Task<ScrollViewer> CreateNewScrollViewer(ImageInfo item)
{
ScrollViewer scrollViewerObj = new ScrollViewer();
byte[] rawData;
try
{
//this will update the values of any older sharpness data to 5
if (item.AnnotationSchemaVersion != null && item.AnnotationSchemaVersion.Equals("1.0", StringComparison.InvariantCulture))
{
item.AdjustmentValue.Sharpness = item.BytePerPixel == 3 ? _samSettingsManager.GetTrueColorSharpnessDefaultValue() : _samSettingsManager.GetSingleColorSharpnessDefaultValue();
var saveSharpness = new Task(() => this.UpdateImageAnalysis(item));
saveSharpness.Start();
}
scrollViewerObj.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_ScrollViewer");
scrollViewerObj.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_ScrollViewer");
scrollViewerObj.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
scrollViewerObj.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
scrollViewerObj.Margin = new Thickness(5, 5, 5, 5);
scrollViewerObj.Focusable = true;
scrollViewerObj.SizeChanged += new SizeChangedEventHandler(ScrollViewerSizeChanged);
Point? fixationTarget = null;
Point? foveaXY = null;
Point? onhXY = null;
FixationType fixationMode = FixationType.Internal;
bool performDistortionCorrection = false;
// Provide fixation values only for WF and Non-External(Non-AnteriorSegment) scans, as distortion correction shall only be applied to WF and Non-External(Non-AnteriorSegment) images.
// All composite UWF/Montage/Auto-Montage images will be distortion corrected (Montage algorithm generates distortion corrected image)
if (Convert.ToInt32(item.FOV, CultureInfo.InvariantCulture) == FOVConstants.Widefield &&
item.ExamMode != ExamModes.AnteriorSegment && SAMConstants.SAMExamSourceUID == item.ExamSourceUID)
{
fixationTarget = item.FixationXY;
foveaXY = item.FoveaXY;
onhXY = item.ONHXY;
fixationMode = item.FixationMode;
performDistortionCorrection = true;
}
//bool isOD = item.Laterality == "OD" ? true : false;
string imageCacheFilePath = _imageCacheFilePath;
string imageFileName = System.IO.Path.GetFileName(item.ImagePath);
//creates the image cache folder if it doesn't exist
if (!Directory.Exists(imageCacheFilePath))
Directory.CreateDirectory(imageCacheFilePath);
ImageContainer imageObj = new ImageContainer(_pixelBufferSize);
await Task.Run(() =>
{
imageObj.Initialize(item.ImagePath, item.ImageCompressionType,
item.ImageWidth, item.ImageHeight, item.BytePerPixel, item.ExamSourceUID, item.Laterality, imageCacheFilePath, _pixelBufferSize, fixationTarget,
foveaXY, item.ProjectedXMin, item.ProjectedYMax, item.ProjectedXMax, item.ProjectedYMin, performDistortionCorrection,
onhXY, fixationMode, item.ONHIdentificationMode);
});
imageObj.InitializeZoomValues(((int)ActualHeight - 40) / 4, ((int)ActualWidth - 40) / 4);
PyramidTools.PyramidImageProcessing processImage = new PyramidTools.PyramidImageProcessing();
//Sets up the pyramid
if (!System.IO.File.Exists(imageCacheFilePath + imageFileName + ExtensionConstants.Raw) || (!System.IO.File.Exists(imageCacheFilePath + imageFileName + ExtensionConstants.Text) && SAMConstants.SAMExamSourceUID == imageObj.ExamSourceUID))
{
rawData = imageObj.ImageDataObj.GetData();
if (rawData != null)
{
processImage.CreatePyramidForGivenImage(rawData, item.BytePerPixel, (int)imageObj.ImageZoom.LowestZoomPercentage, imageFileName, imageObj.ImageDataObj.Width, imageObj.ImageDataObj.Height, imageCacheFilePath);
}
}
else if (!processImage.IsPyramidCreated(imageCacheFilePath + imageFileName, (int)imageObj.ImageZoom.LowestZoomPercentage))
{
rawData = File.ReadAllBytes(imageCacheFilePath + imageFileName + ExtensionConstants.Raw);
if (rawData != null)
{
processImage.CreatePyramidForGivenImage(rawData, item.BytePerPixel, (int)imageObj.ImageZoom.LowestZoomPercentage, imageFileName, imageObj.ImageDataObj.Width, imageObj.ImageDataObj.Height, imageCacheFilePath);
}
}
// For image sharpness
imageObj.ImageProcessing = imageProcessing;
imageObj.TrueColorSharpnessRadius = _trueColorSharpnessRadius;
imageObj.TrueColorSharpnessMinAmount = _trueColorSharpnessMinAmount;
imageObj.TrueColorSharpnessMaxAmount = _trueColorSharpnessMaxAmount;
imageObj.TrueColorSharpnessResizeFactor = _trueColorSharpnessResizeFactor;
imageObj.SingleColorSharpnessRadius = _singleColorSharpnessRadius;
imageObj.SingleColorSharpnessMinAmount = _singleColorSharpnessMinAmount;
imageObj.SingleColorSharpnessMaxAmount = _singleColorSharpnessMaxAmount;
imageObj.SingleColorSharpnessResizeFactor = _singleColorSharpnessResizeFactor;
imageObj.TrueColorSharpnessFactor = _trueColorSharpnessFactor;
imageObj.SingleColorSharpnessFactor = _singleColorSharpnessFactor;
imageObj.IsConstituteImage = item.IsConstituteImage;
imageObj.FOV = item.FOV;
imageObj.SelectedChannel = ChannelTypes.TrueColorChannel;
imageObj.TonalOptimizedValues = new Tonal(128, 128, 128);
imageObj.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_ImageContainer");
imageObj.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_ImageContainer");
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/SAMProduction.FundusImageDisplay;component/Images/RotateBlue.png");
logo.EndInit();
imageObj.ImageRotationShow = new System.Windows.Controls.Image();
imageObj.ImageRotationShow.Source = logo;
imageObj.ImageRotationShow.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_180DegreeIcon");
imageObj.ImageRotationShow.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_180DegreeIcon");
//imageObj.ImageRotationShow.SetResourceReference(Canvas.BackgroundProperty, "180DegreeIcon");
imageObj.ImageRotationShow.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
imageObj.ImageRotationShow.VerticalAlignment = System.Windows.VerticalAlignment.Top;
imageObj.ImageRotationShow.Visibility = System.Windows.Visibility.Collapsed;
imageObj.ImageRotationShow.Width = 30;
imageObj.ImageRotationShow.Height = 30;
imageObj.ImageRotationShow.Margin = new Thickness(0, 10, 0, 0);
imageObj.ImageFrameNoMessage = item.ImageFrameNoMessage;
Style textBlockStyle = this.TryFindResource("TextWhite16") as Style;
#region Top Left Panel Information
StackPanel topLeftPanelInfo = new StackPanel();
topLeftPanelInfo.Width = 160;
topLeftPanelInfo.Name = "TopLeftPanel";
topLeftPanelInfo.Uid = "TopLeftPanel";
topLeftPanelInfo.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
topLeftPanelInfo.VerticalAlignment = System.Windows.VerticalAlignment.Top;
topLeftPanelInfo.Margin = new Thickness(10, 5, 0, 0);
UpdateTopLeftPanel(item, imageObj, topLeftPanelInfo, textBlockStyle);
#endregion
#region Bottom Left Panel Information
StackPanel bottomLeftPanelInfo = new StackPanel();
bottomLeftPanelInfo.Name = "BottomLeftPanel";
bottomLeftPanelInfo.Uid = "BottomLeftPanel";
bottomLeftPanelInfo.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
bottomLeftPanelInfo.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
bottomLeftPanelInfo.Margin = new Thickness(10, 0, 0, 5);
UpdateBottomLeftPanel(item, imageObj, bottomLeftPanelInfo, textBlockStyle);
#endregion
#region Bottom Right Panel Information
StackPanel bottomRightPanelInfo = new StackPanel();
bottomRightPanelInfo.Name = "BottomRightPanel";
bottomRightPanelInfo.Uid = "BottomRightPanel";
bottomRightPanelInfo.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_BottomRightPanelInfo");
bottomRightPanelInfo.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_BottomRightPanelInfo");
bottomRightPanelInfo.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
bottomRightPanelInfo.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
bottomRightPanelInfo.Margin = new Thickness(0, 0, 10, 5);
UpdateBottomRightPanel(item, imageObj, bottomRightPanelInfo, textBlockStyle);
#endregion
#region Top Right Panel Information
StackPanel topRightPanelInfo = new StackPanel();
topRightPanelInfo.Name = "TopRightPanel";
topRightPanelInfo.Uid = "TopRightPanel";
topRightPanelInfo.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_TopRightPanelInfo");
topRightPanelInfo.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_TopRightPanelInfo");
topRightPanelInfo.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
topRightPanelInfo.VerticalAlignment = System.Windows.VerticalAlignment.Top;
topRightPanelInfo.Margin = new Thickness(0, 5, 10, 0);
UpdateTopRightPanel(item, imageObj, topRightPanelInfo, textBlockStyle);
#endregion
Grid gridObj = new Grid() { ClipToBounds = true };//
gridObj.SetValue(AutomationProperties.AutomationIdProperty, "ReviewImageDetailView_Grid");
gridObj.SetValue(AutomationProperties.NameProperty, "ReviewImageDetailView_Grid");
gridObj.Children.Add(imageObj);
if (topLeftPanelInfo != null)
{
gridObj.Children.Add(topLeftPanelInfo);
}
if (bottomLeftPanelInfo != null)
{
gridObj.Children.Add(bottomLeftPanelInfo);
}
if (topRightPanelInfo != null)
{
gridObj.Children.Add(topRightPanelInfo);
}
if (bottomRightPanelInfo != null)
{
gridObj.Children.Add(bottomRightPanelInfo);
}
gridObj.Children.Add(imageObj.SelectedBorder);
gridObj.Children.Add(imageObj.ImageRotationShow);
gridObj.Children.Add(imageObj.OverlayGrid);
imageObj.OverlayGrid.MouseLeftButtonUp += OverlayGrid_MouseLeftButtonUp;
imageObj.OverlayGrid.MouseMove += OverlayGrid_MouseMove;
imageObj.OverlayGrid.MouseLeftButtonDown += OverlayGrid_MouseLeftButtonDown;
imageObj.OverlayGrid.PreviewMouseRightButtonDown += OverlayGrid_PreviewMouseRightButtonDown;
imageObj.OverlayGrid.PreviewMouseRightButtonUp += OverlayGrid_PreviewMouseRightButtonUp;
scrollViewerObj.Content = gridObj;
// This binding required to align image properly when it is loading.
Binding HeightBinding = new Binding();
RelativeSource relativeheightSource = new RelativeSource();
relativeheightSource.Mode = RelativeSourceMode.FindAncestor;
relativeheightSource.AncestorType = typeof(ScrollViewer);
HeightBinding.RelativeSource = relativeheightSource;
HeightBinding.Path = new PropertyPath("ActualHeight");
HeightBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
HeightBinding.Mode = BindingMode.OneWay;
imageObj.SetBinding(System.Windows.Controls.Image.HeightProperty, HeightBinding);
Binding WidthBinding = new Binding();
RelativeSource relativeWidthSource = new RelativeSource();
relativeWidthSource.Mode = RelativeSourceMode.FindAncestor;
relativeWidthSource.AncestorType = typeof(ScrollViewer);
WidthBinding.RelativeSource = relativeWidthSource;
WidthBinding.Path = new PropertyPath("ActualWidth");
WidthBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
WidthBinding.Mode = BindingMode.OneWay;
imageObj.SetBinding(System.Windows.Controls.Image.WidthProperty, WidthBinding);
imageObj.ImageSourceChanged += this.ImageObj_ImageSourceChanged;
imageObj.ZoomValueChanged += this.ImageObj_ZoomValueChanged;
scrollViewerObj.AllowDrop = true;
scrollViewerObj.Drop += ScrollViewer_Drop;
imageObj.ContainerTonalValueChanged += ImageObj_ContainerTonalValueChanged;
// Previously MouseLeftButtonDown event was used.
// Change set no 141851 has change code of CreateNewScrollViewer(). He set Scrollviewer’s Focable property to true.
// It is required to set focusable true for that change set.
// In ScrollViewer's original code (.net code) it is handling event (e.Handled = true) if it can get focus.
// So side effect of 141851 change set is MouseLeftButtonDown event of scrollviewer do not get call when mouse down on it.
// So it misbehaves.
// So here PreviewMouseLeftButtonDown event used.
scrollViewerObj.PreviewMouseLeftButtonDown += ScrollViewerObj_PreviewMouseLeftButtonDown;
scrollViewerObj.MouseLeftButtonUp += this.ScrollViewerObj_MouseLeftButtonUp;
scrollViewerObj.PreviewMouseWheel += ScrollViewerObj_PreviewMouseWheel;
// No need to handle this event
//imageObj.SizeChanged += this.ImageObj_SizeChanged;
imageObj.MouseMove += this.ImageObj_MouseMove;
imageObj.MouseLeftButtonDown += this.ImageObj_MouseLeftButtonDown;
imageObj.MouseLeftButtonUp += this.ImageObj_MouseLeftButtonUp;
gridObj.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
gridObj.VerticalAlignment = System.Windows.VerticalAlignment.Center;
//It is not necessary to initalize the data
imageObj.ImageID = item.ImageId;
//imageObj.ImagePath = item.ImagePath;
if (imageObj.ExamSourceUID == SAMConstants.SAMExamSourceUID &&
imageObj.ExamMode != ExamModes.AnteriorSegment)
imageObj.OverlayGrid.IsHitTestVisible = IsOverlayGridEnable;
else
imageObj.OverlayGrid.IsHitTestVisible = false;
// imageObj.OverlayGrid.IsHitTestVisible = IsOverlayGridEnable;
//imageObj.ImageSource = imageObj.ImageDataObj;
scrollViewerObj.ContextMenu = CreateContextMenu(scrollViewerObj, imageObj); // set contextmenu
}
catch (Exception ex)
{
_services.Logger.Log(LogLevel.Error, "SAMProduction.FundusImageDisplay", "ImageEditViewerBase", "CreateNewScrollViewer: Error occurred while creating new scrollviewer. : " + ex);
}
finally
{
rawData = null;
}
return scrollViewerObj;
}
Please, let me help out to resolve the moved content on top layer of image, if any one can do. Thanks in Advance.
I find creating views in code very unreadable, so this is how to achieve this in XAML:
<Grid>
<Image .../> // or whatever custom control you use to allow zoom
<StackPanel Name="TopLeft HorizontalAligment="Left" VerticalAligment="Top">
<contente: labels etc ../>
</StackPanel>
...
<StackPanel Name="BottomRight" HorizontalAligment="Right" VerticalAligment="Bottom">
<contente: labels etc ../>
</StackPanel>
</Grid>
The trick is to wrap everything that you want to be in the same place and/or overlay in a Grid. If the StackPanels are after an Image in Grid content, their z-index will be higher and they will be displayed on top of the image.
The Image control by default will be streched to the whole grid, so you should manipulate the zoom with its content, not its size. If that's problematic, just wrap the Image control with another panel, or at best, custom UserControl and work out the size issues there.
Thanks to the Grid, the StackPanels will anchored to the corners, no matter the size and shape of the grid.
Also, you used tag MVVM and your code is almost textbook non-MVVM.
Maybe this will help you rewrite your code.

Aspose.Word page number in right margin

i build document with Aspose.Word. I try add page number in right margin. Image better explain it:
My result pdf preview
How to do it?
My current code:
var document = new Document();
_builder = new DocumentBuilder(document)
{
PageSetup =
{
Orientation = Orientation.Portrait,
PaperSize = PaperSize.A4,
RightMargin = ConvertUtil.MillimeterToPoint(20),
BottomMargin = ConvertUtil.MillimeterToPoint(35),
LeftMargin = ConvertUtil.MillimeterToPoint(35),
TopMargin = ConvertUtil.MillimeterToPoint(35)
}
};
_builder.StartTable();
_builder.InsertCell();
_builder.Write("Test test test");
_builder.EndTable();
_builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
_builder.Write("Pages: ");
_builder.InsertField("PAGE", "");
_builder.Write("/");
_builder.InsertField("NUMPAGES");
document.Save(stream, SaveFormat.Pdf);
In your case, you need to add text box in the footer of document, insert page number field in it, and set its position. Please use following modified code example to get the desired output.
var document = new Document();
DocumentBuilder _builder = new DocumentBuilder(document)
{
PageSetup =
{
Orientation = Orientation.Portrait,
PaperSize = Aspose.Words.PaperSize.A4,
RightMargin = ConvertUtil.MillimeterToPoint(20),
BottomMargin = ConvertUtil.MillimeterToPoint(35),
LeftMargin = ConvertUtil.MillimeterToPoint(35),
TopMargin = ConvertUtil.MillimeterToPoint(35)
}
};
_builder.StartTable();
_builder.InsertCell();
_builder.Write("Test test test");
_builder.EndTable();
_builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
Shape shape = new Shape(document, ShapeType.TextBox);
shape.Stroked = false;
shape.Width = _builder.CurrentSection.PageSetup.PageWidth;
shape.Height = 50;
shape.Left = 0;
shape.Left = - _builder.CurrentSection.PageSetup.LeftMargin;
shape.Top = 0;
Paragraph paragraph = new Paragraph(document);
shape.AppendChild(paragraph);
_builder.InsertNode(shape);
_builder.MoveTo(paragraph);
_builder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
_builder.Write("Pages: ");
_builder.InsertField("PAGE", "");
_builder.Write("/");
_builder.InsertField("NUMPAGES");
document.Save(MyDir + "output.pdf", SaveFormat.Pdf);
I work with Aspose as Developer evangelist.

itextsharp table chart legends beneath bars

Can someone explain me how I can create chart like this one using itextsharp library.
As you can see here, this chart has attached table with legends to its bottom side. And each bar has year attached to it. I want to create something like that.
Second picture. This is what i have so far. I don't have year attached to each bar, and my legends are not beneath each bar like in top graph. If someone could guide me how to create identical graph like one on top i would be grateful. Thanks in advance!
How can I turn those labels to be displayed horizontally, and put those legends beneath years in table like one in picture number 1.
// Chart Centers By Year
var chartCentersByYear = new Chart
{
Width = 1000,
Height = 450,
RenderType = RenderType.ImageTag,
AntiAliasing = AntiAliasingStyles.Graphics,
TextAntiAliasingQuality = TextAntiAliasingQuality.High
};
chartCentersByYear.Titles.Add("Centers By Year");
chartCentersByYear.Titles[0].Font = new Font("Arial", 16f);
chartCentersByYear.Titles[0].Alignment = System.Drawing.ContentAlignment.TopLeft;
chartCentersByYear.ChartAreas.Add("");
chartCentersByYear.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chartCentersByYear.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chartCentersByYear.Series.Add("Count");
chartCentersByYear.Series.Add("Cases");
chartCentersByYear.Series[0].ChartType = SeriesChartType.Column; //Pie
chartCentersByYear.Series[1].ChartType = SeriesChartType.StepLine; //StepLine
chartCentersByYear.Series[1].BorderDashStyle = ChartDashStyle.DashDot;
chartCentersByYear.Series[1].BorderWidth = 3;
chartCentersByYear.Series[0].Color = Color.Brown;
chartCentersByYear.Legends.Add("1");
chartCentersByYear.Legends.Add("2");
chartCentersByYear.Legends[0].HeaderSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[0].HeaderSeparatorColor = Color.Black;
chartCentersByYear.Legends[0].ItemColumnSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[0].ItemColumnSeparatorColor = Color.Black;
chartCentersByYear.Legends[1].HeaderSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[1].HeaderSeparatorColor = Color.Black;
chartCentersByYear.Legends[1].ItemColumnSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[1].ItemColumnSeparatorColor = Color.Black;
//For the Legend
LegendCellColumn firstColumn = new LegendCellColumn();
firstColumn.ColumnType = LegendCellColumnType.SeriesSymbol;
firstColumn.HeaderBackColor = Color.WhiteSmoke;
chartCentersByYear.Legends[0].CellColumns.Add(firstColumn);
chartCentersByYear.Legends[1].CellColumns.Add(firstColumn);
LegendCellColumn secondColumn = new LegendCellColumn();
secondColumn.ColumnType = LegendCellColumnType.Text;
secondColumn.Text = "#LEGENDTEXT";
secondColumn.HeaderBackColor = Color.WhiteSmoke;
LegendItem newItemCount = new LegendItem();
newItemCount.Cells.Add(LegendCellType.Text, "Count", System.Drawing.ContentAlignment.MiddleCenter);
newItemCount.BorderWidth = 1;
newItemCount.BorderDashStyle = ChartDashStyle.Solid;
LegendItem newItemCases = new LegendItem();
newItemCases.Cells.Add(LegendCellType.Text, "Cases", System.Drawing.ContentAlignment.MiddleCenter);
newItemCases.BorderWidth = 1;
newItemCases.BorderDashStyle = ChartDashStyle.Solid;
// Getting data from a stored procedure
var totalCentersByYearResult = new Repository().GetTotalCentersByYear();
foreach (IGD_spInternationalReportCenterWithTots1_Result item in totalCentersByYearResult)
{
// For Series
chartCentersByYear.Series[0].Points.AddXY(item.YearEcmo, item.Count);
chartCentersByYear.Series[1].Points.AddY(item.Cases);
// For Legend
newItemCount.Cells.Add(LegendCellType.Text, item.Count.ToString(), System.Drawing.ContentAlignment.MiddleCenter);
newItemCases.Cells.Add(LegendCellType.Text, item.Cases.ToString(), System.Drawing.ContentAlignment.MiddleCenter);
}
chartCentersByYear.Legends[0].CustomItems.Add(newItemCount);
chartCentersByYear.Legends[0].CustomItems.Add(newItemCases);
chartCentersByYear.Legends[0].Docking = Docking.Bottom;
chartCentersByYear.Legends[1].Docking = Docking.Bottom; //Top
chartCentersByYear.Series[0].YAxisType = AxisType.Primary;
chartCentersByYear.Series[1].YAxisType = AxisType.Secondary;
//For two coordinate systems
chartCentersByYear.ChartAreas[0].AxisY2.LineColor = Color.Transparent;
chartCentersByYear.ChartAreas[0].AxisY2.MajorGrid.Enabled = false;
chartCentersByYear.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chartCentersByYear.ChartAreas[0].AxisY2.IsStartedFromZero = chartCentersByYear.ChartAreas[0].AxisY.IsStartedFromZero;
using (var chartimage = new MemoryStream())
{
chartCentersByYear.SaveImage(chartimage, ChartImageFormat.Png);
Byte[] newChart = chartimage.GetBuffer(); //return chartimage.GetBuffer();
var image = Image.GetInstance(newChart); //Image.GetInstance(Chart());
image.ScalePercent(50f);
image.SetAbsolutePosition(document.LeftMargin + 40, document.BottomMargin + 100);
document.Add(image);
}

How to save WebViewBrush as image? (UWP / Universal)

Summary: I have a collection FrameworkElements (basically web view brushes drawn on rectanlges), and I'd like to save each of these as a PNG file in my UWP app.
More details: I followed the example at https://stackoverflow.com/a/17222629/2884981 to split the content of a WebView into separate "pages".
I've put the main bits of code at the bottom.
At the bottom of GetWebPages() I have return pages;
At this point I have a list of all the "pages".
What I'd like to do, is then convert each of those pages into an image (so by the end of it I'd have a collection of PNG files, for instance).
Does anyone know how I can do this? Thanks in advance.
public async Task<WebViewBrush> GetWebViewBrush(WebView webView)
{
// resize width to content
double originalWidth = webView.Width;
var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthString, out contentWidth))
{
throw new Exception(string.Format("failure/width:{0}", widthString));
}
webView.Width = contentWidth;
// resize height to content
double originalHeight = webView.Height;
var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightString, out contentHeight))
{
throw new Exception(string.Format("failure/height:{0}", heightString));
}
webView.Height = contentHeight;
// create brush
var originalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
WebViewBrush brush = new WebViewBrush
{
SourceName = webView.Name,
Stretch = Stretch.Uniform
};
brush.Redraw();
// reset, return
webView.Width = originalWidth;
webView.Height = originalHeight;
webView.Visibility = originalVisibilty;
return brush;
}
And:
public async Task<IEnumerable<FrameworkElement>> GetWebPages(WebView webView, Windows.Foundation.Size page)
{
// ask the content its width
var widthString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollWidth.toString()" });
int contentWidth;
if (!int.TryParse(widthString, out contentWidth))
{
throw new Exception(string.Format("failure/width:{0}", widthString));
}
webView.Width = contentWidth;
// ask the content its height
var heightString = await webView.InvokeScriptAsync("eval", new[] { "document.body.scrollHeight.toString()" });
int contentHeight;
if (!int.TryParse(heightString, out contentHeight))
{
throw new Exception(string.Format("failure/height:{0}", heightString));
}
webView.Height = contentHeight;
// how many pages will there be?
double scale = page.Width / contentWidth;
double scaledHeight = (contentHeight * scale);
double pageCount = (double) scaledHeight / page.Height;
pageCount = pageCount + ((pageCount > (int) pageCount) ? 1 : 0);
// create the pages
var pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)pageCount; i++)
{
var translateY = -page.Height * i;
var rectanglePage = new Windows.UI.Xaml.Shapes.Rectangle
{
Height = page.Height,
Width = page.Width,
Margin = new Thickness(5),
Tag = new TranslateTransform { Y = translateY },
};
rectanglePage.Loaded += (async (s, e) =>
{
var subRectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var subBrush = await GetWebViewBrush(webView);
subBrush.Stretch = Stretch.UniformToFill;
subBrush.AlignmentY = AlignmentY.Top;
subBrush.Transform = subRectangle.Tag as TranslateTransform;
subRectangle.Fill = subBrush;
});
pages.Add(rectanglePage);
}
return pages;
}
I'd like to save each of these as a PNG file in my UWP app.
You can get all the rectangles and show them in the ItemsControl in the NavigationCompleted event of WebView like this:
private async void webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
MyWebViewRectangle.Fill = await GetWebViewBrush(webView);
MyPrintPages.ItemsSource = await GetWebPages(webView, new Windows.Foundation.Size(842, 595));
}
Then in a button click event you can save all the items as .png images like this:
private async void Savetoimage_Clicked(object sender, RoutedEventArgs e)
{
var piclib = Windows.Storage.KnownFolders.PicturesLibrary;
foreach (var item in MyPrintPages.Items)
{
var rect = item as Rectangle;
RenderTargetBitmap renderbmp = new RenderTargetBitmap();
await renderbmp.RenderAsync(rect);
var pixels = await renderbmp.GetPixelsAsync();
var file = await piclib.CreateFileAsync("webview.png", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)rect.Width, (uint)rect.Height,
0, 0, bytes);
await encoder.FlushAsync();
}
}
}

printing a wpf usercontrol on custom paper size

i have a wpf usercontrol with bellow properties:
Width=170mm(642px)
Height=85mm(321px)
i want to print that on a paper with above size(Width=170mm and Height=85mm)
my problem is:when i print it,some items print out of the paper,i think the paper size if Letter by default,if it is correct,how can i change it to above Width and Height?
my code is bellow:
var p = new myUserControl();
var pDoc = new System.Windows.Controls.PrintDialog();
if (pDoc.ShowDialog().Value)
{
pDoc.PrintVisual(p, "MyPrint");
}
maybe something like this needs(this is a settings for System.Windows.Forms.PrintDialog but i use System.Windows.Controls.PrintDialog that it has no PrinterSettings property):
var printerSettings = new PrinterSettings();
var labelPaperSize = new PaperSize { RawKind = (int)PaperKind.A6, Height = 148, Width = 105 };
printerSettings.DefaultPageSettings.PaperSize = labelPaperSize;
var labelPaperSource = new PaperSource { RawKind = (int)PaperSourceKind.Manual };
printerSettings.DefaultPageSettings.PaperSource = labelPaperSource;
if (printerSettings.CanDuplex)
{
printerSettings.Duplex = Duplex.Default;
}
In WPF 1 unit = 1/96 of inch, so you can calculate your size in inches using this formula
you can set printDlg.PrintTicket.PageMediaSize to the size of the Paper and then transform your window to print in that area as below:
private void _print()
{
PrintDialog printDlg = new System.Windows.Controls.PrintDialog();
PrintTicket pt = printDlg.PrintTicket;
Double printableWidth = pt.PageMediaSize.Width.Value;
Double printableHeight = pt.PageMediaSize.Height.Value;
Double xScale = (printableWidth - xMargin * 2) / printableWidth;
Double yScale = (printableHeight - yMargin * 2) / printableHeight;
this.Transform = new MatrixTransform(xScale, 0, 0, yScale, xMargin, yMargin);
//now print the visual to printer to fit on the one page.
printDlg.PrintVisual(this, "Print Page");
}

Categories