In other words, will line 2 in the below code have any effect?
// let's assume that myForm has not previously been added
myControlCollection.Add(myForm);
myControlCollection.Add(myForm); // line 2
I believe that executing Add twice in immediate succession will have no obvious effect. However, if there are intervening Add calls with other controls, it will - because Add updates the Z-order, sending the newly added control to the back. For example:
using System;
using System.Drawing;
using System.Windows.Forms;
class Test
{
static void Main()
{
Form f = new Form();
Button b1 = new Button
{
Location = new Point(50, 50),
Size = new Size(40, 40),
Text = "b1"
};
Button b2 = new Button
{
Location = new Point(70, 70),
Size = new Size(40, 40),
Text = "b2"
};
f.Controls.Add(b1);
f.Controls.Add(b2);
// f.Controls.Add(b1);
Application.Run(f);
}
}
This shows b1 in front of b2 - but if you uncomment the second call to Add(b1), the order will be reversed.
No the second line won't have any effect. The collection won't add the same control instance twice.
No effect will be there on execution of second line.
Related
Updated 10 Nov 2022
I have the following code in a Winforms program:
void CreateCheckBoxes(Control parentControl, int left, int top, int lineSpace)
{
List<string> listVariables = new List<string>() { "AllowColumnReorder", "CaptureFocusClick", "ColScaleMode", "ColumnTracking", "RowTracking", "EnsureVisible", "FullRowSelect", "GridLines", "HideSelection", "HoverSelection", "IsFocused", "LabelEdit", "MultiSelect", "Scrollable", "VisualStyles" };
foreach (string varName in listVariables)
{
CheckBox ctlTemp = new CheckBox { Name = "chk" + varName, Text = varName, Top = top, Left = left };
parentControl.Controls.Add(ctlTemp);
top += lineSpace;
}
chkAllowColumnReorder.CheckedChanged += new EventHandler(chkAllowColumnReorder_CheckedChanged);
// The name 'chkAllowColumnReorder' does not exist in the current context
}
It works to the extent that I can create as many CheckBoxes as I like based on the length of listVariables. However, I want the name of the CheckedChanged event handler to be based on the name of the control.
As well as my original question I now find I cannot refer to the CheckBox by the name provided in { Name = "chk" + varName, in the debugger a watch on "Name" returns the name of the form. I have not used this form of constructor before and am struggling to find any documentation on it. Can anybody help on this before I try to move on again please?
Is there a way to do this?
The code itself is produced by a small program where I just past in the names of variables from the main program and it produces the above, and all the vent handlers, which is an enormous time saver.
jimi - I've posted this as an answer as it's too long for a comment.
I ended up with:
Dictionary<string, Action<CheckBox>> m_Actions = new Dictionary<string, Action<CheckBox>>();
then loop through:
m_Actions.Add("chkAllowColumnReorder", (c) => containerListView1.AllowColumnReorder = c.Checked); etc.
and then:
void chkTemp_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkTemp = ((CheckBox)sender);
m_Actions[chkTemp.Name](chkTemp);
}
This is completely new to me and I'm still not sure how (or why) it works but thank you very much for telling me about it - I can now paste variables in to my app's form and produce all the code to add controls to the app I need to test.
I did it because my heart sank at the thought of adding heaps of CheckBoxes to an app to test an ExtendeListView, in the end writing this to produce the code was much more interesting than the testing!
I need to show/hide some data points in oxyplot line series. Is it possible?
Though some markers are invisible, the line should go through the invisible markers.
You could make use of two series to achieve this. The first one would draw the complete points (and line) without the marker. The second series would draw the visible points(with marker,but with line style set to none). For Example
DataPoint[] points = new DataPoint[]
{
new DataPoint(1,12),
new DataPoint(2,10),
new DataPoint(3,9),
new DataPoint(4,13),
new DataPoint(5,14),
new DataPoint(6,10)
};
var seriesComplete = new OxyPlot.Series.LineSeries();
seriesComplete.Points.AddRange(points);
var seriesVisible = new OxyPlot.Series.LineSeries();
seriesVisible.Points.AddRange(points.Where(x => x.Y % 2 == 0));
seriesVisible.MarkerFill = OxyColors.Blue;
seriesVisible.MarkerType = MarkerType.Circle;
seriesVisible.MarkerSize = 10;
seriesVisible.LineStyle = LineStyle.None;
this.MyModel.Series.Add(seriesComplete);
this.MyModel.Series.Add(seriesVisible);
Result is attached as image
Is there an easy/straightforward way to dynamically add (not edit the value of) multiple checkbox controls in a .docx document body?
I tried appending a single SdtContentCheckBox after a new paragraph like this but with no luck:
newParagraph.Append(new SdtContentCheckBox());
and also followed the instructions here:
https://www.codeproject.com/Tips/370758/Add-dynamic-content-controls-to-a-word-document and here: How do I create a check box in C# using Open XML SDK
The first one showed only how to add a text content control and the second one straight up resulted in a corrupted .docx file.
Any help would be appreciated!
Closest working code I could find was this:
https://social.msdn.microsoft.com/Forums/office/en-US/f6ce8ecf-0ed8-4f18-958a-a086f212d1e2/how-to-create-a-checked-checkbox-form-field-using-the-sdk?forum=oxmlsdk
public static Paragraph GenerateParagraph()
{
var element =
new Paragraph(
new Run(
new FieldChar(
new FormFieldData(
new FormFieldName(){ Val = "Check1" },
new Enabled(),
new CalculateOnExit(){ Val = BooleanValues.Zero },
new CheckBox(
new AutomaticallySizeFormField(),
new DefaultCheckboxFormFieldState(){ Val = BooleanValues.Zero }))
){ FieldCharType = FieldCharValues.Begin }),
new BookmarkStart(){ Name = "Check1", Id = 0 },
new Run(
new FieldCode(" FORMCHECKBOX "){ Space = "preserve" }),
new Run(
new FieldChar(){ FieldCharType = FieldCharValues.End }),
new BookmarkEnd(){ Id = 0 },
new Run(
new Text("My check box"))
){ RsidParagraphAddition = "00784880", RsidRunAdditionDefault = "00B77989" };
return element;
}
Using this I was able to dynamically add Legacy Checkboxes (i.e. neither Content control nor ActiveX control), but at least it is a start!
If someone knows how to add Checkbox Content controls, feel free to post a reply below and I'll mark it as Correct.
Even though you found yourself the answer, I'll leave this here in case anyone stumbles upon this looking for something related.
There's a tool called Open XML SDK 2.5 Productivity Tool, which you can download from here that allows you to reverse-engineer a word .docx document to obtain the C# code to generate it from scratch.
In order to get the code that you are looking for to generate any kind of word element (a checkbox, a table, a bulleted list...), you need to create a word document with said element and save it.
Then, open it using the Open XML SDK 2.5 Productivity Tool and click on the "Reflect Code" button. The generated code will show you how to create those elements, styles and other formatting included.
With that, I got the code necessary to get a paragraph with a checkbox
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
public static Paragraph GenerateCheckboxParagraph(string internalName, int internalId, string textAfterTextbox)
{
var run1 = new Run(
new FieldChar(
new FormFieldData(
new FormFieldName() { Val = internalName },
new Enabled(),
new CalculateOnExit() { Val = OnOffValue.FromBoolean(false) },
new CheckBox(
new AutomaticallySizeFormField(),
new DefaultCheckBoxFormFieldState() { Val = OnOffValue.FromBoolean(false) }))
)
{
FieldCharType = FieldCharValues.Begin
}
);
var run2 = new Run(new FieldCode(" FORMCHECKBOX ") { Space = SpaceProcessingModeValues.Preserve });
var run3 = new Run(new FieldChar() { FieldCharType = FieldCharValues.End });
var run4 = new Run(new Text(textAfterTextbox));
var element =
new Paragraph(
run1,
new BookmarkStart() { Name = internalName, Id = new StringValue(internalId.ToString()) },
run2,
run3,
new BookmarkEnd() { Id = new StringValue(internalId.ToString()) },
run4
);
return element;
}
Derived from Jeff S's methodology found here, I can add a "Checkbox" to a PDF page like so:
PdfPTable tblFirstRow = new PdfPTable(5);
tblFirstRow.SpacingBefore = 4f;
tblFirstRow.HorizontalAlignment = Element.ALIGN_LEFT;
. . . // code where textboxes are added has been elided for brevity
PdfPCell cell204Submitted = new PdfPCell()
{
CellEvent = new DynamicCheckbox("checkbox204Submitted", "204 Submitted or on file")
};
tblFirstRow.AddCell(cell204Submitted);
doc.Add(tblFirstRow);
The DynamicCheckbox class, based on Jeff S's CustomCellLayout class, is:
public class DynamicCheckbox : IPdfPCellEvent
{
private string fieldname;
private string cap;
public DynamicCheckbox(string name, String caption)
{
fieldname = name;
cap = caption;
}
public void CellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases)
{
PdfWriter writer = canvases[0].PdfWriter;
RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
ckbx.CheckType = RadioCheckField.TYPE_CHECK;
ckbx.Text = cap;
PdfFormField field = ckbx.CheckField;
writer.AddAnnotation(field);
}
}
My problem is that the checkbox's text (the string assigned to ckbx.Text) is not displaying. The checkbox (outsized) occupies the last cell in the table row, but there is no (visible) accompanying text.
What's missing from my code?
Note: I tried to reduce the size of the checkbox by doing this:
Rectangle tangle = new Rectangle(20, 20);
//RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
RadioCheckField ckbx = new RadioCheckField(writer, tangle, fieldname, "Yes");
...but that attempt failed - with that code, I can't even "find" the checkbox in the generated PDF file - clicking willy-nilly in column 5 conjures up no checkbox...
Others have answered the label part. The Rectangle that you have called "tangle" needs to be calculated off of the rectangle that comes into the event handler, similar to
Rectangle tangle = new Rectangle(
rectangle.Left,
rectangle.Top - PDFStyle.boxsize - 4.5f,
rectangle.Left + PDFStyle.boxsize,
rectangle.Top - 4.5f
);
Where PDFStyle.boxsize is the width/height of the checkbox and 4.5f is the padding the edge of the cell. Basically the rectangle isn't relative to the cell, but absolute to the page.
As described in ISO-32000-1, a check box is a field of type Button. If you define text for a button, you want to define the text that is displayed on the button. However: in the case of a check box, there is no such text! Instead, you have two appearances, one for the Off value and one for the Yes value.
An educated guess made by an attentive reader would be that you don't want to add text (to the button), but that you want to add a label (for a checkbox). Again you should consult ISO-32000-1 and you'll discover that the spec doesn't say anything about labels for check boxes. The concept just doesn't exist at the level of an AcroForm.
This doesn't mean the concept doesn't exist in general. Many PDF tools allow you to define check boxes that are preceded by a label. When you look inside the PDF, you'll discover that this label is just part of the content, whereas the check box is represented by a widget orientation.
Let's take a look at the official documentation instead of frustrating ourselves searching on every place of the web except on the official web site. More specifically: let's take a look at the Buttons example from Chapter 7 of my book. You'll see that one can set text for a real button:
PushbuttonField button = new PushbuttonField(writer, rect, "Buttons");
button.setText("Push me");
This isn't possible with check boxes (for the obvious reason that the appearance of a check box is completely different). If we want to add a label, we can add it for instance like this:
checkbox = new RadioCheckField(writer, rect, LANGUAGES[i], "Yes");
field = checkbox.getCheckField();
field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", onOff[0]);
field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Yes", onOff[1]);
writer.addAnnotation(field);
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT,
new Phrase(LANGUAGES[i], font), 210, 790 - i * 40, 0);
You can find the C# version of these examples here: http://tinyurl.com/itextsharpIIA2C07
Creating a checkbox, and then accompanying text to its right, can be done like this:
PdfPCell cell204Submitted = new PdfPCell()
{
CellEvent = new DynamicCheckbox("checkbox204Submitted")
};
tblFirstRow.AddCell(cell204Submitted);
// . . . Chunks and an anchor created; that code has been elided for brevity
Paragraph parCkbxText = new Paragraph();
parCkbxText.Add(Chunk204SubmittedPreamble);
parCkbxText.Add(ChunkBoldNote);
parCkbxText.Add(Chunk204Midsection);
parCkbxText.Add(anchorPayeeSetup204);
PdfPCell cellCkbxText = new PdfPCell(parCkbxText);
cellCkbxText.BorderWidth = PdfPCell.NO_BORDER;
tblFirstRow.AddCell(cellCkbxText);
public class DynamicCheckbox : IPdfPCellEvent
{
private string fieldname;
public DynamicCheckbox(string name)
{
fieldname = name;
}
public void CellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases)
{
PdfWriter writer = canvases[0].PdfWriter;
RadioCheckField ckbx = new RadioCheckField(writer, rectangle, fieldname, "Yes");
ckbx.CheckType = RadioCheckField.TYPE_CHECK;
ckbx.BackgroundColor = BaseColor.ORANGE;
ckbx.FontSize = 6;
ckbx.TextColor = BaseColor.WHITE;
PdfFormField field = ckbx.CheckField;
writer.AddAnnotation(field);
}
}
question 1. I have this issue of "Object reference not set to an instance of an object" when my Majorlabel is empty and this occurs after i try to do a save button click on xml serialization. How can i fix this?
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
string savepath;
SaveFileDialog DialogSave = new SaveFileDialog();
// Default file extension
DialogSave.DefaultExt = "txt";
// Available file extensions
DialogSave.Filter = "XML file (*.xml)|*.xml|All files (*.*)|*.*";
// Adds a extension if the user does not
DialogSave.AddExtension = true;
// Restores the selected directory, next time
DialogSave.RestoreDirectory = true;
// Dialog title
DialogSave.Title = "Where do you want to save the file?";
// Startup directory
DialogSave.InitialDirectory = #"C:/";
DialogSave.ShowDialog();
savepath = DialogSave.FileName;
DialogSave.Dispose();
DialogSave = null;
FormSaving abc = new FormSaving();
if (!string.IsNullOrEmpty(MajorversionresultLabel.Content.ToString()))
{
abc.Majorversion = MajorversionresultLabel.Content.ToString();
}
abc.Startzbuildfrom = StartzbuildcomboBox.SelectedItem.ToString();
using (Stream savestream = new FileStream(savepath, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(FormSaving));
serializer.Serialize(savestream, abc);
}
}
As recommended,
here is the line of error:
if (!string.IsNullOrEmpty(MajorversionresultLabel.Content.ToString()))
{
abc.Majorversion = MajorversionresultLabel.Content.ToString();
}
Question 2. I used this line to save my combo box selection:
abc.Startzbuildfrom = StartzbuildcomboBox.SelectedItem.ToString();
and in my load i have this line:
StartzbuildcomboBox.SelectedItem = abc.Startzbuildfrom
why wont it select the combobox selection previously?
As a first note, I'd recommend only putting one question into a single query here. Makes it easier.
For your second question, my guess is that you're running into a reference variable problem. I think that calling the ToString() method on the SelectedItem actually creates an entirely new string variable. Then, when you try to set the selected item later, it can't find the new string as a possible item to select because, even though the two strings have the same value, they are different objects. I would maybe recommend that you either:
1) Set the selected item by searching through your combo box contents to find a string whose value matches the one you've saved
or
2) Save the actual reference by saying abc.Startzbuildfrom = StartzbuildcomboBox.SelectedItem. Then set the selected item from that reference.
I suspect that MajorversionresultLabel is null, or MajorversionresultLabel.Content is null. Thus your statement
if (!string.IsNullOrEmpty(MajorversionresultLabel.Content.ToString()))
will throw a NullReferenceException. Try this instead:
if (MajorversionresultLabel != null && MajorversionresultLabel.Content != null && MajorversionLabel.Content.ToString() != string.Empty)
I bet your NullReferenceException will go away.