سری 6 قسمتی در رابطه با User Stories
در ادامه مثالی را بررسی خواهیم کرد که بر اساس ردیفهای گزارش آن، یک نمودار، به انتهای گزارش اضافه خواهد شد.
کدهای کامل این مثال را در ذیل مشاهده میکنید:
using System; using System.Collections.Generic; using PdfReportSamples.Models; using PdfRpt.Core.Contracts; using PdfRpt.Core.Helper; using PdfRpt.FluentInterface; namespace PdfReportSamples.ChartImage { public class ChartImagePdfReport { public IPdfReportData CreatePdfReport() { var chart = new MSChartHelper { AxisXTitle = "User", AxisYTitle = "Balance", ChartTitle = "Users Balance", AxisTitleFont = new System.Drawing.Font("Tahoma", 12f), LabelStyleFont = new System.Drawing.Font("Tahoma", 10f), ChartTitleFont = new System.Drawing.Font("Arial", 16f, System.Drawing.FontStyle.Bold), LegendsFont = new System.Drawing.Font("Tahoma", 12f) }; return new PdfReport().DocumentPreferences(doc => { doc.RunDirection(PdfRunDirection.RightToLeft); doc.Orientation(PageOrientation.Portrait); doc.PageSize(PdfPageSize.A4); doc.DocumentMetadata(new DocumentMetadata { Author = "Vahid", Application = "PdfRpt", Keywords = "Test", Subject = "Test Rpt", Title = "Test" }); }) .DefaultFonts(fonts => { fonts.Path(string.Format("{0}\\fonts\\irsans.ttf", AppPath.ApplicationPath), string.Format("{0}\\fonts\\verdana.ttf", Environment.GetEnvironmentVariable("SystemRoot"))); }) .PagesFooter(footer => { footer.DefaultFooter(printDate: DateTime.Now.ToString("MM/dd/yyyy")); }) .PagesHeader(header => { header.DefaultHeader(defaultHeader => { defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png"); defaultHeader.Message("گزارش جدید ما"); }); }) .MainTableTemplate(template => { template.BasicTemplate(BasicTemplate.ClassicTemplate); }) .MainTablePreferences(table => { table.ColumnsWidthsType(TableColumnWidthType.Relative); }) .MainTableDataSource(dataSource => { var listOfRows = new List<User>(); for (var i = 0; i < 7; i++) { listOfRows.Add(new User { Id = i, LastName = "نام خانوادگی " + i, Name = "نام " + i, Balance = (i * 50) + 1000 }); } dataSource.StronglyTypedList(listOfRows); }) .MainTableEvents(events => { events.DataSourceIsEmpty(message: "There is no data available to display."); events.DocumentOpened(args => { chart.ChartInit(width: (int)args.PdfWriter.PageSize.Width - 100, height: 250); }); events.RowAdded(args => { if (args.RowType == RowType.DataTableRow) { var name = args.TableRowData.GetValueOf<User>(x => x.Name); if (name == null) return; var balance = args.TableRowData.GetValueOf<User>(x => x.Balance); if (balance == null) return; chart.AddXY(name, balance); } }); events.DocumentClosing(args => { chart.AddChartToPage(args.PdfDoc); chart.FreeResources(); }); }) .MainTableSummarySettings(summary => { summary.OverallSummarySettings("جمع"); summary.PreviousPageSummarySettings("نقل از صفحه قبل"); }) .MainTableColumns(columns => { columns.AddColumn(column => { column.PropertyName("rowNo"); column.IsRowNumber(true); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(0); column.Width(1); column.HeaderCell("ردیف", captionRotation: 90); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Id); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(1); column.Width(2); column.HeaderCell("شماره"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Name); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(2); column.Width(2); column.HeaderCell("نام"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.LastName); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(3); column.Width(3); column.HeaderCell("نام خانوادگی"); }); columns.AddColumn(column => { column.PropertyName<User>(x => x.Balance); column.HeaderCell("موجودی"); column.ColumnItemsTemplate(template => { template.TextBlock(); template.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)); }); column.Width(2); column.AggregateFunction(aggregateFunction => { aggregateFunction.NumericAggregateFunction(AggregateFunction.Sum); aggregateFunction.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)); }); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.IsVisible(true); column.Order(4); }); }) .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\RptChartSample.pdf")); } } }
using System.Drawing; using System.IO; //It's part of the .NET 4.0+ now. using System.Windows.Forms.DataVisualization.Charting; using iTextSharp.text; using iTextSharp.text.pdf; using PdfRpt.Core.Helper; namespace PdfReportSamples.ChartImage { public class MSChartHelper { // MS Chart learning tutorials: // http://weblogs.asp.net/scottgu/archive/2010/02/07/built-in-charting-controls-vs-2010-and-net-4-series.aspx Chart _chart; public System.Drawing.Font AxisTitleFont { set; get; } public string AxisXTitle { set; get; } public string AxisYTitle { set; get; } public string ChartTitle { set; get; } public System.Drawing.Font ChartTitleFont { set; get; } public System.Drawing.Font LabelStyleFont { set; get; } public System.Drawing.Font LegendsFont { set; get; } public void AddChartToPage(Document pdfDoc, int scalePercent = 100, float spacingBefore = 20, float spacingAfter = 10, float widthPercentage = 80) { using (var chartimage = new MemoryStream()) { _chart.SaveImage(chartimage, ChartImageFormat.Bmp); //BMP gives the best compression result var iTextSharpImage = PdfImageHelper.GetITextSharpImageFromByteArray(chartimage.GetBuffer()); iTextSharpImage.ScalePercent(scalePercent); iTextSharpImage.Alignment = Element.ALIGN_CENTER; var table = new PdfPTable(1) { WidthPercentage = widthPercentage, SpacingBefore = spacingBefore, SpacingAfter = spacingAfter }; table.AddCell(iTextSharpImage); pdfDoc.Add(table); } } public void AddXY(object xValue, params object[] yValue) { _chart.Series[0].Points.AddXY(xValue, yValue); } public void ChartInit(int width, int height) { _chart = new Chart { Width = width, Height = height, AntiAliasing = AntiAliasingStyles.All, TextAntiAliasingQuality = TextAntiAliasingQuality.High, Palette = ChartColorPalette.BrightPastel, BackColor = ColorTranslator.FromHtml("#F3DFC1"), BackGradientStyle = GradientStyle.TopBottom }; setBorder(); setTitles(); setChartAreas(); setLegends(); setSeries(); } public void FreeResources() { if (_chart != null && !_chart.IsDisposed) _chart.Dispose(); } private void setBorder() { _chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss; _chart.BorderlineWidth = 2; _chart.BorderlineColor = Color.FromArgb(181, 64, 1); _chart.BorderlineDashStyle = ChartDashStyle.Solid; } private void setChartAreas() { _chart.ChartAreas.Add("ChartArea1"); _chart.ChartAreas[0].AxisX.Title = AxisXTitle; _chart.ChartAreas[0].AxisY.Title = AxisYTitle; _chart.ChartAreas[0].AxisX.TitleFont = AxisTitleFont; _chart.ChartAreas[0].AxisY.TitleFont = AxisTitleFont; _chart.ChartAreas[0].AxisX.LabelStyle.Font = LabelStyleFont; _chart.ChartAreas[0].AxisX.LabelStyle.Angle = -90; _chart.ChartAreas[0].BackColor = Color.White; _chart.ChartAreas[0].AxisX.LineColor = Color.FromArgb(64, 64, 64); _chart.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64); _chart.ChartAreas[0].AxisY.LineColor = Color.FromArgb(64, 64, 64); _chart.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64); } private void setLegends() { _chart.Legends.Add("Default"); _chart.Legends[0].LegendStyle = LegendStyle.Row; _chart.Legends[0].IsTextAutoFit = false; _chart.Legends[0].DockedToChartArea = "ChartArea1"; _chart.Legends[0].Docking = Docking.Bottom; _chart.Legends[0].IsDockedInsideChartArea = false; _chart.Legends[0].BackColor = Color.Transparent; _chart.Legends[0].Font = LegendsFont; } private void setSeries() { _chart.Series.Add(""); _chart.Series[0].ChartType = SeriesChartType.Column; _chart.Series[0].Palette = ChartColorPalette.EarthTones; _chart.Series[0].IsValueShownAsLabel = true; _chart.Series[0].IsVisibleInLegend = false; } private void setTitles() { _chart.Titles.Add(ChartTitle); _chart.Titles[0].Font = ChartTitleFont; _chart.Titles[0].TextStyle = TextStyle.Shadow; _chart.Titles[0].ShadowOffset = 3; _chart.Titles[0].ShadowColor = Color.FromArgb(32, 0, 0); _chart.Titles[0].Alignment = ContentAlignment.TopCenter; _chart.Titles[0].ForeColor = Color.FromArgb(26, 59, 105); } } }
توضیحات:
- استفاده از MSChart در اینجا از این جهت مناسب است که فراگیری کار کردن با آن عمومی بوده و در پروژههای وب و ویندوز کاربرد دارد و احتمالا هم اکنون با نحوه کارکردن با آن آشنا هستید، زیرا از سال 2010 به دات نت اضافه شده است.
- در این بین تنها متد جدید و مهم کلاس MSChartHelper، متد AddChartToPage آن است. به کمک متد chart.SaveImage میتوان تصویر نهایی معادل یک نمودار را در حافظه ذخیره کرد. سپس با استفاده از متد PdfImageHelper.GetITextSharpImageFromByteArray، این تصویر موجود در حافظه را به معادل قابل استفاده آن در iTextSharp تبدیل کرده و به صفحه اضافه خواهیم کرد.
- در کدهای اصلی تولید گزارش، مقدار دهی کلاس کمکی MSChartHelper در قسمت رخدادهای قابل استفاده PdfReport در متد MainTableEvents آن انجام شده است:
در روال رویدادگردان DocumentOpened، بر اساس عرض واقعی صفحه، عرض نمودار را مشخص میکنیم:
events.DocumentOpened(args => { chart.ChartInit(width: (int)args.PdfWriter.PageSize.Width - 100, height: 250); });
events.RowAdded(args => { if (args.RowType == RowType.DataTableRow) { var name = args.TableRowData.GetValueOf<User>(x => x.Name); if (name == null) return; var balance = args.TableRowData.GetValueOf<User>(x => x.Balance); if (balance == null) return; chart.AddXY(name, balance); } });
events.DocumentClosing(args => { chart.AddChartToPage(args.PdfDoc); chart.FreeResources(); });
مقایسهای بین Mapperly و AutoMapper
LINQPad is a powerful testing tool for all .NET developers that can help them deliver solutions in less time. In Getting the Most from LINQPad Succinctly, returning Succinctly series author José Roberto Olivas Mendoza lays out different ways to extend the functionality built into LINQPad. In this ebook, you’ll learn how to use LINQPad to query Entity Framework models in Visual Studio, how to work with the LINQPad command-line utility, how to write your own extensions and visualizers, and how to write custom data context drivers.
-
A Quick Tour of LINQPad
-
LINQPad and Entity Framework
-
LINQPad Scripting
-
LINQPad Extensibility
-
Custom Data Context Drivers
نگاهی به NET Standard 2.0.
کتابخانه jquery-image-player
Fill and FillByObject
/// <summary> /// Insert values from an object into a string pattern. To specify the object's property you have to use the '{propertyName}'. /// </summary> /// <remarks> /// This method is a replacement to String.Format, but it has two differences: /// <list type="simple"> /// <item>It reverese the order you call the functionality, instead of writing String.Format(pattern, args) you write pattern.FillByObject(args). This makes the code look cleaner.</item> /// <item>You supply the pattern with an object and specify insertion points by property names.</item> /// </list> /// <example> /// <![CDATA[ /// "First name:{firstName}, Sur name:{Surname}".FillByObject(new {firstName = "Sam", lastName="Naseri"}); /// ]]> /// </example> /// </remarks> /// <seealso cref="Fill"/> /// <typeparam name="T">Type of bindingValue.</typeparam> /// <param name="bindingPattern">The pattern to fill.</param> /// <param name="bindingValue">The object providing values to fill in the pattern.</param> /// <returns>The pattern filled with values.</returns> public static string FillByObject<T>(this string bindingPattern, T bindingValue) { var properties = GetProperties(typeof(T)).ToList(); var values = properties.Select(property => property.GetValue(bindingValue, new object[] { })).ToList(); var result = bindingPattern; for (int index = 0; index < properties.Count; index++) { var property = properties[index]; var propPattern = "{" + property.Name + "}"; var old = result; result = result.Replace(propPattern, values[index] != null ? values[index].ToString() : ""); } return result; }
private static IEnumerable<PropertyInfo> GetProperties(Type t) { return t.GetProperties(BindingFlags.Public | BindingFlags.Instance); }
/// <summary> /// A simple replacement for String.Format which only makes the codes look nicer. /// </summary> /// <param name="pattern">The source string that you want to replace insertion points on it.</param> /// <param name="args">Values to be replaced in the pattern.</param> /// <returns></returns> public static string Fill(this string pattern, params object[] args) { return string.Format(pattern, args); }
آموزش توسعه یک بلاگ با Blazor Server
Build a Complete Blog App with Blazor Server - Step-by-Step Tutorial from Scratch by Abhay Prince
You will learn about fundamentals of Blazor Server, Routing, Shared Reusable Components, Custom Authentication, EF Core Code First, Passing data from parent to child components and vice versa, Passing events from child to parent components, Forms validations and submissions, styling components, using javascript with blazor. third party components integration with blazor, blazor lifecycle events, authentication and authorization in blazor server, programtically navigating between component pages, multiple routes paths for single component page, dynamic routes and getting data from routes, authorized view and much more...