Well i trying to Print A Customized QR Code with Some String.
the problem i am facing is Not Able to Place the Strings in Correct Places in short Not Able to Customize the Output.
And what i getting is jumbled . can i create Template and Print That ?
Customization Code
CurrentY = 0;
CurrentX = 0;
InvSubTitleHeight = (int)(InvSubTitleFont.GetHeight(g));
// Get Titles Length:
int lenInvSubTitle1 = (int)g.MeasureString("Bill ID : " + billId, InvSubTitleFont).Width;
int lenInvSubTitle2 = (int)g.MeasureString("Bill Amount : " + billAmt, InvSubTitleFont).Width;
int lenInvSubTitle3 = (int)g.MeasureString("Date : " + DateTime.Now.ToString("dd/MM/yyyy"), InvSubTitleFont).Width;
// Set Titles Left:
int xInvSubTitle1 = CurrentX + lenInvSubTitle1 / 2;
int xInvSubTitle2 = CurrentX + lenInvSubTitle2 / 2;
int xInvSubTitle3 = CurrentX + lenInvSubTitle3 / 2;
// Draw Invoice Head:
if (billId != "")
{
CurrentY = CurrentY + InvSubTitleHeight;
g.DrawString("Bill ID : " + billId, InvSubTitleFont, BlackBrush, 0, CurrentY);
}
if (billAmt != "")
{
CurrentY = CurrentY + InvSubTitleHeight + 5;
g.DrawString("Bill Amount : " + billAmt, InvSubTitleFont, BlackBrush, 0, CurrentY);
}
CurrentY = CurrentY + InvSubTitleHeight + 5;
g.DrawString("Date : " + DateTime.Now.ToString("dd/MM/yyyy"), InvSubTitleFont, BlackBrush, 0, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 15;
var image = QRValidation.CreateImage(img);
var p = new Point(0, CurrentY);
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(image, p);
CurrentY += image.Height + 20;
//Add bottom Text
g.DrawString("Scan the image above with your", InvSubTitleFont, BlackBrush, 0, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 2;
g.DrawString("X app and earn reward", InvSubTitleFont, BlackBrush, 0, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 2;
g.DrawString("points for your last purchase", InvSubTitleFont, BlackBrush, 0, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 25;
g.DrawString("You can scan this QR Code only", new Font("Times New Roman", 10, FontStyle.Bold), BlackBrush, 0, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 3;
g.DrawString("once.", new Font("Times New Roman", 10, FontStyle.Bold), BlackBrush, 90, CurrentY);
// Draw line:
CurrentY = CurrentY + InvSubTitleHeight + 25;
var width = (int) g.MeasureString("Powered by X", InvSubTitleFont).Width;
g.DrawLine(new Pen(Brushes.DarkCyan, 3), CurrentX, CurrentY, width+2, CurrentY);
CurrentY = CurrentY + InvSubTitleHeight + 5;
g.DrawString("Powered by X", InvSubTitleFont, BlackBrush, 0, CurrentY);
Related
EPPlus has no support for extLst thing which is needed to make databars conditional formatting with solid fill. They are gradient by themselves without modifications.
I coded this to modify worksheet's xml directly (this gets databars from worksheet XML and then adds required extLst nodes):
public static Random Rnd = new Random();
public static string GenerateXlsId()
{
//{29BD882A-B741-482B-9067-72CC5D939236}
string id = string.Empty;
for (int i = 0; i < 32; i++)
if (Rnd.NextDouble() < 0.5)
id += Rnd.Next(0, 10);
else
id += (char)Rnd.Next(65, 91);
id = id.Insert(8, "-");
id = id.Insert(13, "-");
id = id.Insert(18, "-");
id = id.Insert(23, "-");
return id;
}
public static void FixDatabarsAtWorksheet(OfficeOpenXml.ExcelWorksheet eworksheet)
{
System.Xml.XmlNodeList databars = eworksheet.WorksheetXml.GetElementsByTagName("dataBar");
if (databars.Count > 0)
{
string conditional_formattings_str = string.Empty;
for (int i = 0; i < databars.Count; i++)
{
string temp_databar_id = GenerateXlsId();
databars[i].ParentNode.InnerXml += #"<extLst>
<ext uri=""{B025F937-C7B1-47D3-B67F-A62EFF666E3E}"" xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:id>{" + temp_databar_id + #"}</x14:id>
</ext>
</extLst>";
//--
string temp_sqref = databars[i].ParentNode.ParentNode.Attributes["sqref"].Value;
string left_type = string.Empty;
string left_val = string.Empty;
string right_type = string.Empty;
string right_val = string.Empty;
string color = string.Empty;
Color databar_fill_color = Color.Empty;
Color databar_border_color = Color.Empty;
for (int j = 0; j < databars[i].ChildNodes.Count; j++)
if (databars[i].ChildNodes[j].LocalName == "cfvo" && databars[i].ChildNodes[j].Attributes["type"] != null)
{
if (string.IsNullOrEmpty(left_type))
left_type = databars[i].ChildNodes[j].Attributes["type"].Value;
else if (string.IsNullOrEmpty(right_type))
right_type = databars[i].ChildNodes[j].Attributes["type"].Value;
if (databars[i].ChildNodes[j].Attributes["val"] != null)
if (string.IsNullOrEmpty(left_val))
left_val = databars[i].ChildNodes[j].Attributes["val"].Value;
else if (string.IsNullOrEmpty(right_val))
right_val = databars[i].ChildNodes[j].Attributes["val"].Value;
}
else if (databars[i].ChildNodes[j].LocalName == "color")
{
color = databars[i].ChildNodes[j].Attributes["rgb"].Value;
int argb = Int32.Parse(color, System.Globalization.NumberStyles.HexNumber);
databar_fill_color = Color.FromArgb(argb);
databar_border_color = Color.FromArgb(255,
databar_fill_color.R - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.R - 50,
databar_fill_color.G - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.G - 50,
databar_fill_color.B - 50 < 0 ? databar_fill_color.R + 50 : databar_fill_color.B - 50);
}
string temp_conditional_formatting_template = #"<x14:conditionalFormatting xmlns:xm=""http://schemas.microsoft.com/office/excel/2006/main"">
<x14:cfRule type=""dataBar"" id=""{" + temp_databar_id + #"}"">
<x14:dataBar minLength=""" + (string.IsNullOrEmpty(left_val) ? "0" : left_val) + "\" maxLength=\"" + (string.IsNullOrEmpty(right_val) ? "100" : right_val) + "\" gradient=\"0\" " + (databar_border_color.IsEmpty ? string.Empty : "border = \"1\"") + ">";
temp_conditional_formatting_template += Environment.NewLine + "<x14:cfvo type=\"" + (left_type.ToLower() == "min" ? "autoMin" : left_type) + "\" />";
temp_conditional_formatting_template += Environment.NewLine + "<x14:cfvo type=\"" + (right_type.ToLower() == "max" ? "autoMax" : right_type) + "\" />";
if (!databar_border_color.IsEmpty)
temp_conditional_formatting_template += Environment.NewLine + "<x14:borderColor rgb=\"" + BitConverter.ToString(new byte[] { databar_border_color.A, databar_border_color.R, databar_border_color.G, databar_border_color.B }).Replace("-", "") + "\" />";
temp_conditional_formatting_template += Environment.NewLine + #"</x14:dataBar>
</x14:cfRule>
<xm:sqref>" + temp_sqref + #"</xm:sqref>
</x14:conditionalFormatting>";
conditional_formattings_str += temp_conditional_formatting_template;
}
databars[0].ParentNode.ParentNode.ParentNode.InnerXml += #"<extLst>
<ext uri=""{78C0D931-6437-407d-A8EE-F0AAD7539E65}"" xmlns:x14=""http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"">
<x14:conditionalFormattings>" + conditional_formattings_str + #"
</x14:conditionalFormattings>
</ext>
</extLst>";
}
}
And this really makes databars solid fill, the problem is any other conditional formatting like GreaterThan loses it's style when true.
For example I add databar and GreaterThan 123 (green) conditional formattings.
Excel still see coditional formatting rule GreaterThan 123, but the style is not set when it's true (green is not set). While databars is displayed correctly at same time.
I don't know where to look... Someone help!
Thats the problem with hacks - they are so fragile! :)
I was able to get it work with another hack - setting the style differential formatting (dxf) reference which seems to be dropped when epplus saves. What might be happening is epplus only thinks there is one dxf on save so it doesnt set the value since excel will assume it is the first dxf style (index 0) but that is a bit of a guess.
Anyway, if you set the dxfid via XML manually it will find it. But order counts here, you have to apply the databar hack last otherwise it will hit the wrong reference:
[TestMethod]
public void FixDatabarsAtWorksheetTest()
{
//https://stackoverflow.com/questions/58417819/how-to-stop-other-conditional-formatting-from-disappearing-when-hackmodding-data
//Throw in some data
var datatable = new DataTable("tblData");
datatable.Columns.AddRange(new[]
{
new DataColumn("Col1", typeof(int)), new DataColumn("Col2", typeof(int)), new DataColumn("Col3", typeof(object))
});
for (var i = 0; i < 10; i++)
{
var row = datatable.NewRow();
row[0] = i;
row[1] = i * 10;
row[2] = Path.GetRandomFileName();
datatable.Rows.Add(row);
}
//Create a test file
var fi = new FileInfo(#"c:\temp\FixDatabarsAtWorksheetTest.xlsx");
if (fi.Exists)
fi.Delete();
using (var pck = new ExcelPackage(fi))
{
var workbook = pck.Workbook;
var doc = workbook.Worksheets.Add("Sheet1");
doc.Cells.LoadFromDataTable(datatable, true);
//Set the greater than
var gtConditional = doc
.ConditionalFormatting
.AddGreaterThan(doc.Cells["A2:A11"]);
gtConditional.Formula = "2";
gtConditional.Style.Fill.BackgroundColor.Color = Color.GreenYellow;
//Fix the gt
var xdoc = doc.WorksheetXml;
var nsm = new XmlNamespaceManager(xdoc.NameTable);
nsm.AddNamespace("default", xdoc.DocumentElement.NamespaceURI);
var gtNode = xdoc.SelectSingleNode("/default:worksheet/default:conditionalFormatting[#sqref=\"A2:A11\"]", nsm);
//Create the new attribute for table
var att = xdoc.CreateAttribute("dxfId");
att.Value = "0";
gtNode
.FirstChild
.Attributes.Append(att);
//Set the bar condition LAST
var barConditional = doc
.ConditionalFormatting
.AddDatabar(doc.Cells["B2:B11"], Color.FromArgb(99, 195, 132));
barConditional.HighValue.Type = eExcelConditionalFormattingValueObjectType.Num;
barConditional.LowValue.Type = eExcelConditionalFormattingValueObjectType.Num;
barConditional.HighValue.Value = 82;
barConditional.LowValue.Value = 0;
FixDatabarsAtWorksheet(doc);
pck.Save();
}
}
I get this:
Not sure how feasible this is for you depending on how many conditional formats you have but its worth a shot.
XpsDocument is loaded from disk
Create a FixedDocumentSequence via XpsDocument.GetFixedDocumentSequence Method ()
Display the via a DocumentViewer
Would like to add to add header and footer to print
I don't need to add the header and footer back to the XPS document - only to the print output
I tried implementing DocumentPaginator but cannot get the sizing or placement to work
NOT the same as this footer to FlowDocument
I use the solution there for FlowDocuments just fine
Convert XAML Flow Document to XPS with Style
On the FixedDocumentSequence the sizing comes from document (I guess)
For example could mix landscape and portrait
I cannot figure out how to hook into the sizing and make room for a header and footer
I can stamp a header on it but it is over the top of the page
And landscape pages are cut off
Cannot assign a PageSize when it comes from a FixedDocumentSequence
As stated in the link it is a suggested pages size
DocumentPage.Size is read only
Even if I create DocumentPage of the Size I want when the page is loaded using DocumentPaginator.GetPage then the Size is overwritten
Even worse the DocumentPaginator does not seem to be properly aware of the Size as it does not deal with mixed landscape and portrait properly. Landscape is printed portrait and just runs off the page.
some one asked me to post code
there also might be a just plain better approach
see footer to FlowDocument for how to use it
this is where it breaks
// this gets the page size from GetPage - ignores size above
public class DocumentPaginatorWrapperXPS : DocumentPaginator
{
System.Windows.Size m_PageSize;
System.Windows.Size m_Margin;
DocumentPaginator m_Paginator;
FixedDocumentSequence fixedDocumentSequence;
Typeface m_Typeface;
private string printHeader;
private int? sID;
private string docID;
public DocumentPaginatorWrapperXPS(FixedDocumentSequence FixedDocumentSequence, System.Windows.Size margin, string PrintHeader, int? SID, string DOCID)
{
//m_PageSize = pageSize;
//m_PageSize = new Size(800, 600);
fixedDocumentSequence = FixedDocumentSequence;
m_Margin = margin;
m_Paginator = fixedDocumentSequence.DocumentPaginator;
//m_Paginator.PageSize = new System.Windows.Size(m_PageSize.Width - margin.Width * 2,
// //m_PageSize.Height - margin.Width * 2);
printHeader = PrintHeader;
sID = SID;
docID = DOCID;
}
Rect Move(Rect rect)
{
if (rect.IsEmpty)
{
return rect;
}
else
{
return new Rect(rect.Left + m_Margin.Width, rect.Top + m_Margin.Height,
rect.Width, rect.Height);
}
}
private Size sizeXPS;
public override DocumentPage GetPage(int pageNumber)
{
System.Windows.Documents.DocumentPage page = m_Paginator.GetPage(pageNumber);
Debug.WriteLine(page.Size.Width + " " + page.Size.Height);
m_Paginator.PageSize = new System.Windows.Size(page.Size.Width/2 - m_Margin.Width * 2, page.Size.Height/2 - m_Margin.Height * 2);
page = m_Paginator.GetPage(pageNumber); // this get the page size from GetPage - ignores size above
Debug.WriteLine(page.Size.Width + " " + page.Size.Height);
DynamicDocumentPaginator paginatorPage = fixedDocumentSequence.DocumentPaginator as DynamicDocumentPaginator;
paginatorPage.PageSize = new System.Windows.Size(page.Size.Width / 2 - m_Margin.Width * 2, page.Size.Height / 2 - m_Margin.Height * 2);
sizeXPS = new System.Windows.Size(page.Size.Width / 2 - m_Margin.Width * 2, page.Size.Height / 2 - m_Margin.Height * 2);
page = paginatorPage.GetPage(pageNumber); // still does not change the page size
Debug.WriteLine(page.Size.Width + " " + page.Size.Height);
//page.PageSize = new System.Windows.Size(m_PageSize.Width - margin.Width * 2,
//m_PageSize.Height - margin.Width * 2);
//page.Size = new System.Windows.Size(page.Size.Width - m_Margin.Width * 2, page.Size.Height - m_Margin.Height * 2);
//page.Size.Width = page.Size.Width - m_Margin.Width * 2;
// Create a wrapper visual for transformation and add extras
ContainerVisual newpage = new ContainerVisual();
DrawingVisual title = new DrawingVisual();
using (DrawingContext ctx = title.RenderOpen())
{
if (m_Typeface == null)
{
m_Typeface = new Typeface("Segoe UI Symbol"); //Ariel
}
//FormattedText text = new FormattedText("Attorney eyes only \uE18B \u1F440 Page " + (pageNumber + 1),
// System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
// m_Typeface, 14, System.Windows.Media.Brushes.Black);
string pageS = "m_PageSize.Width " + m_PageSize.Width + " m_Margin.Width " + m_Margin.Width + " m_PageSize.Height " + m_PageSize.Height + " m_Margin.Height " + m_Margin.Height + Environment.NewLine +
"page.Size.Width " + page.Size.Width + " page.Size.Height " + page.Size.Height;
FormattedText header = new FormattedText("\u1F440 " + printHeader + Environment.NewLine + pageS,
System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
m_Typeface, 14, System.Windows.Media.Brushes.Black);
ctx.DrawText(header, new System.Windows.Point(96 / 2, -96 / 4)); // 1/4 inch above page content
//text = new FormattedText(pageS, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
// m_Typeface, 14, System.Windows.Media.Brushes.Black);
string goGabe = string.Empty;
if (sID != null)
{
goGabe += Environment.NewLine + "Gabriel Docs™ sysDocID: " + sID;
if (!string.IsNullOrEmpty(docID))
goGabe += " docID: " + docID;
}
goGabe += Environment.NewLine + "Page: " + (pageNumber + 1) + " Date: " + DateTime.Now.ToString() + " User: " + App.StaticGabeLib.CurUserP.UserID;
FormattedText footer = new FormattedText(goGabe
, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
m_Typeface, 14, System.Windows.Media.Brushes.Black);
ctx.DrawText(footer, new System.Windows.Point(96 / 2, page.Size.Height - m_Margin.Height));
//ctx.DrawText(footer, new System.Windows.Point(96 / 2, m_Paginator.PageSize.Height - m_Margin.Height));
}
DrawingVisual background = new DrawingVisual();
using (DrawingContext ctx = background.RenderOpen())
{
ctx.DrawRectangle(new SolidColorBrush(System.Windows.Media.Color.FromRgb(240, 240, 240)), null, page.ContentBox);
}
newpage.Children.Add(background); // Scale down page and center
ContainerVisual smallerPage = new ContainerVisual();
smallerPage.Children.Add(page.Visual);
smallerPage.Transform = new MatrixTransform(0.8, 0, 0, 0.8, 0.1 * page.ContentBox.Width, 0.1 * page.ContentBox.Height);
newpage.Children.Add(smallerPage);
newpage.Children.Add(title);
newpage.Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height);
return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox));
}
public override bool IsPageCountValid
{
get
{
return m_Paginator.IsPageCountValid;
}
}
public override int PageCount
{
get
{
return m_Paginator.PageCount;
}
}
public override System.Windows.Size PageSize
{
get
{
Debug.WriteLine("PageSize " + sizeXPS.Width + " " + sizeXPS.Height);
return sizeXPS; // this is not called
//m_Paginator.PageSize;
}
set
{
sizeXPS = value;
// m_Paginator.PageSize = value;
}
}
public override IDocumentPaginatorSource Source
{
get
{
return m_Paginator.Source;
}
}
}
I'm trying to print a page with the previously created users.
The PrintPreviewDialog show up correctly formatted but when I click the print button the printer prints a blank page.
I also get blank page with using the PrintDialog(). I assigned the PrintDocument value for both PrintDialog() and PrintPreviewDialog() from the form designer properties.
Here is my code. Thanks for your help. Regards.
private void printButton_Click_1(object sender, EventArgs e)
{
if (userGenerator != null)
{
try
{
printDocument.DefaultPageSettings.PaperSize = new PaperSize("A4", 827, 1170);
if (imageLogo == null)
{
userCount = 0;
printDocument.PrintPage += new PrintPageEventHandler(pd_PrintPage);
}
else
{
userCount = 0;
printDocument.PrintPage += new PrintPageEventHandler(pd_PrintPage_WithImage);
}
printPreviewDialog.ShowDialog();
if (printDialog.ShowDialog() == DialogResult.OK)
{
printDocument.Print();
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured while printing", ex.ToString());
}
}
else
{
MessageBox.Show("You have to create users first.");
}
}
private void pd_PrintPage_WithImage(object sender, PrintPageEventArgs ev)
{
int userX = 15, userY = 70;
int lineCount = 0;
int linesPerPage = 9;
User.User printedUser = null;
if (userCount < userGenerator.users.Count)
{
printedUser = userGenerator.users[userCount];
}
for (int i = userCount; i < userGenerator.users.Count; i++)
{
if (lineCount < linesPerPage)
{
printedUser = userGenerator.users[userCount];
//Horizontal line
ev.Graphics.DrawLine(Pens.Black, userX, userY, userX + 250, userY);
//Draw logo
ev.Graphics.DrawImage(imageLogo, userX + 100, userY + 5, 40, 40);
ev.Graphics.DrawString("Username: " + printedUser.username + Environment.NewLine + "Password: " + printedUser.password, printFont, Brushes.Black, userX, userY + 60);
//Horizontal lines
ev.Graphics.DrawLine(Pens.Black, userX, userY + 50, userX + 250, userY + 50);
ev.Graphics.DrawLine(Pens.Black, userX, userY + 120, userX + 250, userY + 120);
//Vertical lines
ev.Graphics.DrawLine(Pens.Black, userX, userY, userX, userY + 120);
ev.Graphics.DrawLine(Pens.Black, userX + 250, userY, userX + 250, userY + 120);
userCount++;
if (userCount % 3 == 0)
{
userX = 15;
userY += 120;
lineCount++;
}
else
{
userX += 270;
}
}
}
if (printedUser != null && userCount < userGenerator.users.Count)
{
ev.HasMorePages = true;
}
else
{
ev.HasMorePages = false;
}
}
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
int userX = 15, userY = 70;
int lineCount = 0;
int linesPerPage = printFont.Height;
User.User printedUser = null;
if (userCount < userGenerator.users.Count)
{
printedUser = userGenerator.users[userCount];
}
for (int i = userCount; i < userGenerator.users.Count; i++)
{
if (lineCount < linesPerPage)
{
printedUser = userGenerator.users[userCount];
ev.Graphics.DrawString("Username: " + printedUser.username + Environment.NewLine + "Password: " + printedUser.password, printFont, Brushes.Black, userX, userY);
ev.Graphics.DrawLine(Pens.Black, userX, userY, userX + 250, userY);
ev.Graphics.DrawLine(Pens.Black, userX, userY + 50, userX + 250, userY + 50);
ev.Graphics.DrawLine(Pens.Black, userX, userY, userX, userY + 50);
ev.Graphics.DrawLine(Pens.Black, userX + 250, userY, userX + 250, userY + 50);
userCount++;
if (userCount % 3 == 0)
{
userX = 15;
userY += 50;
lineCount++;
}
else
{
userX += 270;
}
}
}
if (printedUser != null && userCount < userGenerator.users.Count)
{
ev.HasMorePages = true;
}
else
{
ev.HasMorePages = false;
}
}
I'm getting the error:-
error: cannot find symbol
tofile.println("Dancing" + " " + danceminutes + " " + bpm);
^
symbol: variable tofile
location: class CreateFile
I'm not sure why.
// writing to a file
PrintWriter toFile = new PrintWriter(new FileWriter("exLog.txt"));
Random randy = new Random();
int count = randy.nextInt(12) + 19;
for (int i = count; i > 0; i--) {
int exercise = randy.nextInt(3);
if (exercise == 0) {
int minutesOne = randy.nextInt(47) + 14;
int minutesTwo = randy.nextInt(62) + 59;
int minutesThree = randy.nextInt(122) + 119;
int roulette = randy.nextInt(100);
if (roulette <= 74) {
int runoneminutes = minutesOne;
double speed = 4.9 + (16.1 - 4.9) * randy.nextDouble();
double distance = speed * runoneminutes/60;
tofile.println("Running" + " " + runoneminutes + " " + distance);
}
else if (roulette > 74 && roulette < 96) {
int runtwominutes = minutesTwo;
double twospeed = 4.9 + (16.1 - 4.9) * randy.nextDouble();
double twodistance = twospeed * runtwominutes/60;
tofile.println("Running" + " " + runtwominutes + " " + twodistance);
}
else if (roulette >= 96) {
int runthreeminutes = minutesThree;
double threespeed = 4.9 + (16.1 - 4.9) * randy.nextDouble();
double threedistance = threespeed * runthreeminutes/60;
tofile.println("Running" + " " + runthreeminutes + " " + threedistance);
}
}
if (exercise == 1) {
int bikeminutesOne = randy.nextInt(62) + 29;
int bikeminutesTwo = randy.nextInt(212) + 89;
int bikeroulette = randy.nextInt(100);
if (bikeroulette <= 49) {
int bikeoneminutes = bikeminutesOne;
double bikeonespeed = 7.9 + (25.1 - 7.9) * randy.nextDouble();
double bikeonedistance = bikeonespeed * bikeoneminutes/60;
tofile.println("Biking" + " " + bikeoneminutes + " " + bikeonedistance);
}
else if (bikeroulette > 49) {
int biketwominutes = bikeminutesTwo;
double biketwospeed = 7.9 + (25.1 - 7.9) * randy.nextDouble();
double biketwodistance = biketwospeed * biketwominutes/60;
tofile.println("Biking" + " " + biketwominutes + " " + biketwodistance);
}
}
if (exercise == 2) {
int exercises = randy.nextInt(15) + 1;
int reps = randy.nextInt(37) + 9;
double liftminutes;
int liftminutes = 5*reps*exercises/60 + 2*(exercises-1);
tofile.println("Lifting" + " " + liftminutes + " " + reps);
}
if (exercise == 3) {
int danceminutes = randy.nextInt(90) + 29;
double bpm = 79.9 + (220 - 79.9) * randy.nextDouble();
tofile.println("Dancing" + " " + danceminutes + " " + bpm);
}
}
toFile.close(); //saving output file
} // end main
} // end CreateFile class
The variable name is toFile. The compiler is complaining about the use of 'tofile'.
So I have a wrappanel which is wrapped vertically. The items are added at run-time, but all those items (user controls) have different widths and because the wrappanel is wrapped vertically, it stacks them dowm and when they cover the vertical space they wrap to the next column. BUT what I need is "kind of" two way wrapping, i.e. I added a first item which is 200px in width, then I added a second item which is like 50px in width, but when I add a third item which is like 100px in width I want it to not to go to the next row, but place itself in that free spot the 50px control left there depending on that 200px control on top (that leaves a 150px space and a 100px control clearly fits). Of course when it doesn't fit, it wraps to the next row, and that's all OK.
Here's an images to clarify this (Can't upload'em here):
That's what happens:
image 1
And that's what I want:
image 2
Sorry for my english, it's not my primary language. I hope you'll understand my question.
You definitely can't use a single panel to accomplish that! You can use a stackpanel where to insert multiple and dynamic wrappanel with horizontal orientation to have "column" behavior you need
Well, I did it. Just wrote a custom wrappanel with the behavior I wanted.
Here it is:
public class TwoWayWrapPanel : Panel
{
int _rowCount = 0;
public int RowCount
{
get { return _rowCount; }
set { _rowCount = value; }
}
protected override Size MeasureOverride(Size availableSize)
{
Size resultSize = new Size(0, 0);
double columnWidth = 0;
double usedSpace = 0;
double nullX = 0;
double currentX = 0;
double currentY = 0;
bool isFirst = true;
int row = 0;
foreach (UIElement child in Children)
{
child.Measure(availableSize);
if (isFirst)
{
columnWidth = child.DesiredSize.Width;
resultSize.Width += columnWidth;
currentY += child.DesiredSize.Height;
row++;
isFirst = false;
}
else
{
if (columnWidth >= usedSpace + child.DesiredSize.Width & _rowCount > 1)
{
currentX = nullX + usedSpace;
usedSpace += child.DesiredSize.Width;
}
else
{
row++;
if (row + 1 > _rowCount | child.DesiredSize.Width > columnWidth)
{
row = 0;
currentX = nullX + columnWidth;
nullX = currentX;
usedSpace = 0;
columnWidth = child.DesiredSize.Width;
currentY = child.DesiredSize.Height;
row++;
resultSize.Width += columnWidth;
}
else
{
currentY += child.DesiredSize.Height;
currentX = nullX;
usedSpace = child.DesiredSize.Width;
}
}
}
}
return resultSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
double columnWidth = 0;
double usedSpace = 0;
double nullX = 0;
double currentX = 0;
double currentY = 0;
bool isFirst = true;
int row = 0;
foreach (UIElement child in Children)
{
//First item in the collection
if (isFirst)
{
child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
columnWidth = child.DesiredSize.Width;
currentY += child.DesiredSize.Height;
row++;
isFirst = false;
}
else
{
//Current item fits so place it in the same row
if (columnWidth >= usedSpace + child.DesiredSize.Width & _rowCount > 1)
{
currentX = nullX + usedSpace;
child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
usedSpace += child.DesiredSize.Width;
}
else
{
row++;
//The row limit is reached or the item width is greater than primary item width. Creating new column
if (row + 1 > _rowCount | child.DesiredSize.Width > columnWidth)
{
row = 0;
currentY = 0;
currentX = nullX + columnWidth;
nullX = currentX;
usedSpace = 0;
child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
columnWidth = child.DesiredSize.Width;
currentY += child.DesiredSize.Height;
row++;
}
//Item doesn't fit. Adding to the new row in the same column
else
{
usedSpace = 0;
currentY += child.DesiredSize.Height;
currentX = nullX;
child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
usedSpace += child.DesiredSize.Width;
}
}
}
}
return finalSize;
}
}