Dynamic control in c# - c#

I want to create a kind of 4 x 3 matrix with textboxes and checkboxes. Whether the element is checkbox or textbox depends upon the values in database.I want it to be dynamic. What is the best way to start?
// something like this but I need to fill in each elements of the matrix...
private void CreateSpecificControl(string requestedType)
{
if (requestedType == "CheckBox")
{
CheckBox control1 = new CheckBox();
control1.Click += new EventHandler(chk_CheckedChanged);
//TableLayout panel
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));
layout.Controls.Add(control1);
}
else
{
Label control1 = new Label();
control1.Text = "Not a checkbox";
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));
layout.Controls.Add(control1);
}
}

Use a usercontrol. See this tutorial.
At run time you can change the contents of the User control. There's a Controls collection in each user control that you can add or remove elements from. For example if you want to add check boxes just do somethign like this:
myUserControl.Controls.Add(new CheckBox());
Similarly elements can be removed from this collection, thus achieving a dynamic behaviour.

Related

Getting list of checked radiobuttons in .net

TLDR; Looking for a method to retrieve all radiobuttons by means of something like this... (psudo)
List<RadioButton> btn = new List<RadioButton>;
btn = stackPanel.getAllRadioButtons()
I am currently building a little quiz application in C#. I have functions that add the required GUI elements to a groupbox. I would like to know if there is any way that I can loop through the created elements (for instance radio buttons) to see which are checked.
Here is one of the functions along with how they are added to the window.
private void tfQ(string questionBody)
{
StackPanel questionPanel = new StackPanel{Orientation = Orientation.Vertical};
questionPanel.Children.Add(new Label { Content = questionBody });
GroupBox group = new GroupBox();
RadioButton trueRadio = new RadioButton();
trueRadio.Content = "True";
RadioButton falseRadio = new RadioButton();
falseRadio.Content = "False";
questionPanel.Children.Add(trueRadio);
questionPanel.Children.Add(falseRadio);
group.Content = questionPanel;
mainStack.Children.Add(group);
}
Constructor:
public quiz()
{
tfQ("This is a true/false question");
Window w = new Window();
w.Content = mainStack;
w.Show();
}
I have found many ways to do it in the C# scripting format
(using the Control function ...)
var checkedButton = container.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
but I have not yet found a "programmatic" way of doing it. I have considered changing the type of void tfQ to a StackPanel, but that only helps me to easier loop through the stack panels, althought that only partly solves me problem - allows me to easier loop through the StackPanels but I still don't know how to get the RadioButtons on a panel.
P.S I am very new to C# - with experience in Java/C/C++/Python
I made use of the following code to cast the content into a new groupbox and stackpanel, respectively.
if (child is GroupBox)
{
if ((child as GroupBox).Content is StackPanel)
{
StackPanel d = (StackPanel)((GroupBox)child).Content;
}
}
This allowed me to cast the content into a local copy of a control. It may not be the best way - I'm sure it is very inefficient to be honest. Solved the problem.

How to scroll bottom row of TableLayoutPanel into view

At runtime I am adding controls to a control that inherits from TableLayoutPanel. Controls are added one at a time, based on user interaction, not in a loop.
Here's the setup of my control that inherits from the TLP:
this.RowCount = 0;
this.RowStyles.Clear();
this.Dock = DockStyle.Fill;
this.VerticalScroll.Enabled = true;
this.HorizontalScroll.Enabled = false;
this.AutoScroll = true
And I'm adding user-controls to the bottom of the panel like this:
var uc = new FooControl();
this.Controls.Add(uc);
this.SetRow(uc, this.Controls.Count - 1);
this.SetColumn(uc, 0);
I would like to scroll that row/control into view.
How is that done?
To scroll a control into view in a ScrollableControl like TableLayoutPanel, you can use ScrollControlIntoView method. For example:
this.ScrollControlIntoView(uc);
Note: It doesn't select the control.
Also If you call Select method of a control, it will be selected (if selectable) and also its scrollable parent will be scrolled to bring the selected child control into view. For example:
uc.Select();
You can do that by setting the VerticalScroll of the Panel but I think it would be better to use ScrollControlIntoView instead.
private void panel1_ControlAdded(object sender, ControlEventArgs e)
{
panel1.ScrollControlIntoView(e.Control);
}
or
panel.VerticalScroll.Value = panel.VerticalScroll.Maximum

Create checkbox next to each label

I need this page to be very easily maintained, so I need most of the stuff to be programmatically generated. I need to create checkboxes next to normal Labels, without touching the .aspx file. right now I generate a list with all labels on my page called labels. Each label on my site has an ID beginning with lbl_, but the ones that are supposed to have a checkbox begin with lblx_. I then want to use something like this to create said checkboxes:
foreach (Label label in labels)
{
if (label.ID.Contains("lblx_"))
{
CheckBox cb = new CheckBox();
cb.ID = "cb_statistikname_" + label.ID;
label.Controls.AddAt(0, cb);
}
}
Right now this code replaces the labels, the same happens when I use label.Control.Add(cb)
You can use Page.Controls.AddAt() with combination of page.Page.Controls.IndexOf()
if(label.Parent != null && label.Parent.Controls.IndexOf(label) >= 0)
label.Parent.Controls.AddAt(label.Parent.Controls.IndexOf(label) + 1, cb);
Note :This should be done in Page PreInit events.
If you set the Text property in your Label control, basically all child controls get wiped out. See this answer: asp:label doesn't render children

C# All Check-box Appearance

In my WinForms Visual Studio application i have a checkbox styled as a Flat Button with this C# code:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (TestBox.Checked == true)
{
TestBox.Image = Image.FromFile("M:\\CheckBox_52x.png");
TestBox.ImageAlign = ContentAlignment.MiddleCenter;
TestBox.FlatAppearance.BorderSize = 0;
// make all four (!) BackColors transparent!
TestBox.BackColor = System.Drawing.Color.Transparent;
TestBox.FlatAppearance.CheckedBackColor = Color.Transparent;
TestBox.FlatAppearance.MouseDownBackColor = Color.Transparent;
}
else
{
TestBox.Image = Image.FromFile("M:\\CheckBoxUncheck_52x.png");
TestBox.ImageAlign = ContentAlignment.MiddleCenter;
TestBox.FlatAppearance.BorderSize = 0;
// make all four (!) BackColors transparent!
TestBox.BackColor = System.Drawing.Color.Cyan;
TestBox.FlatAppearance.CheckedBackColor = Color.Cyan;
TestBox.FlatAppearance.MouseDownBackColor = Color.Cyan;
}
}
I was wondering, if instead of doing this to every single checkbox in my application, can i make the "UNCHECKED" version i have coded the default checkbox style for this applicatiom - eg - every time i create a new one it appears with these properties.
Please keep in mind that i am brand new to coding in C#.
If you want multiple controls to use the same eventhandler, that's easy - just use the same event handler. Change your code to something like:
private void HandleCheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox checkBox = (CheckBox) sender;
string imageFile;
Color color;
if (checkBox.Checked == true)
{
// TODO: Use resources embedded within your app
imageFile = "M:\\CheckBox_52x.png";
color = Color.Transparent;
}
else
{
imageFile = "M:\\CheckBoxUncheck_52x.png";
color = Color.Cyan;
}
// TODO: Load each file once and reuse the bitmap, I suspect.
checkBox.Image = Image.FromFile(imageFile);
checkBox.ImageAlign = ContentAlignment.MiddleCenter;
checkBox.FlatAppearance.BorderSize = 0;
checkBox.BackColor = color;
checkBox.FlatAppearance.CheckedBackColor = color;
checkBox.FlatAppearance.MouseDownBackColor = color;
}
You can then attach the same handler to all your checkboxes.
If you have multiple classes, you could make that a public static method. At that point you may need to add the event handler in code rather than getting the designer to do it - I don't know whether the designer knows how to use static methods for event handlers. But it would just be something like:
TestBox.CheckedChanged += CheckBoxUtilities.HandleCheckBoxCheckedChanged;
That's if you really just want the same code to be used for event handlers. Other things to consider are:
Constructing a subclass of CheckBox as suggested by rakatherock. My own experience with creating custom controls in Windows Forms has not been great, but from an OO perspective it feels fine. An initial implementation could just derive from CheckBox and implicitly add an event handler which does exactly what your current code does.
If you want to find all the CheckBox controls in a form at some point, you can use the Controls property and then recurse through any control which itself a container. I won't go into the details of that now though, as it sounds like you don't really want this - unless you did it just to find all the CheckBox controls and add the same event handler to all of them.
This can be done by creating custom checkbox control.
From the question what you are trying to do is to manipulate all check boxes in the application from a single check box so here the logic goes like:
Save the All checkbox value(Checked or unchecked) in the settings
To create a settings value
Right Click Project>Properties>Settings>Give Name as someBoolValue,type as bool,Scope as User
So on CheckChanged event of this check box save the value in Settings variable that we have created just now.In CheckChangedEvent of main All Check box code goes like:
Properties.Settings.Default.someBoolValue=cbCheckBox.Checked;
Properties.Settings.Default.Save();
Now on every form load are where ever the event is suitable do like
foreach(Control c in this.Controls)
{
if(c is CheckBox)
{
c.Checked=Properties.Settings.Default.someBoolValue
}
}
Note:You can replace all the check box that i implemented with your custom controls.I have given you just an idea how to do it.

TabControl tab buttons location

I'm looking for solution for my problem. I want to change location for tabcontrol's TabButtons or add control assigned to tabpage but outside TabControl. TabPages are added dynamically. Example:
Form1___________ _ [] X
_______________________
Some TabPage content
Tab1 | Tab2 | Tab3 | < >
TextBox assigned to Tab's
________________________
So if I change tabs by clicking on Tab1,Tab2,Tab3 TabPage + TextBox content should change depending on Tab. The first idea was to put TabButtons on bottom and add ArrayList what contains TextBox content, catch TabControl change tab event and change TextBox content, but there was an issue with editing and adding that content. In few words: I wan't to put TabButtons between 2 controls(for example between two textboxes).Do you have any ideas?
If I understand what you're asking for... You want when you click on a tab, it controls two different things? Like two different text boxes?
If that is true, you should be able to do it like this.
foreach (thing in your ArrayList)
{
TabPage tabPage = new TabPage("Name of tab"); // Add a new tab page
RichTextBox rtb = new System.Windows.Forms.RichTextBox();//RTF box
TextBox tb = new System.Windows.Forms.TextBox(); //Text box
//Set up size, position and properties
rtb.LoadFile("some/Path/to/a/file");
//set up size, position of properties
tb.Text = "Some text I want to display";
tabPage.Controls.Add(rtb); //Add both boxes to that tab
tabPage.Controls.Add(tb);
tabControl1.TabPages.Add(tabPage); //Add that page to the tab control
}
Only thing you should have to mess around with is the layout. And make sure to have the tabControl added with the designer.
you can create your own textbox class which inherits from textbox class :
class MyOwnTextBox:TextBox
{
public int parent_tab;
}
So you can add your textbox by assigning a parent_tab id to them . so in tab button click event , you can do something like that :
foreach(MyOwnTextBox txt in this.Controls)
{
if(txt.parent_tab==1) txt.visible=false;
}
You could also place the tabs on the left or the right side of your tab control. That is not perfect, but would come closer to your idea than placing them above or below the tab control.
You can add a new tab page dynamically like this
tabControl1.TabPages.Add("My new Tab");
I'm not sure I understand exactly what your trying to do. If you want to change the tab from another object, just use:
TabController.SelectTab(0);
If you want to remove a TabPage and add it to another, use:
TabController.Controls.Remove(TabPage1);
TabController2.Controls.Add(TabPage1);
Edit: From further read, I think you want something like this:
this.TabController.ControlAdded += AddLinksToBottomOfTabs;
public void mainSettingsTabController_ControlAdded(object sender, ControlEventArgs e)
{
//Create label with e.Control.Name as the title and
//add it to wherever you want it added.
}

Categories