I have created a small kitchen display program that display food orders. So I created dynamically a panel that contains a table layout panel that contains a checked list box and a check all button . My problem is... I have a check all button in each table layout panel created dynamically and every time I click it, it checks all items in the last created CheckedListBox not the clicked one.
This is my code:
p = new Panel();
p.Size = new System.Drawing.Size(360, 500);
p.BorderStyle = BorderStyle.FixedSingle;
p.Name = "panel";
tpanel = new TableLayoutPanel();
tpanel.Name = "tablepanel";
clb = new CheckedListBox();
tpanel.Controls.Add(b1 = new Button() { Text = "CheckAll" }, 1, 4);
b1.Name = "b1";
b1.Click += new EventHandler(CheckAll_Click);
b1.AutoSize = true;
private void CheckAll_Click(object sender, EventArgs e)
{
var buttonClicked = (Button)sender;
var c = GetAll(this, typeof(CheckedListBox));
for (int i = 0; i < c.Count(); i++)
{
\\any help
}
}
public IEnumerable<Control> GetAll(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type)).Concat(controls).Where(c =>
c.GetType() == type);
}
First I will describe the struct
Order = TableLayoutPanel
TableLayoutPanel has 1 CheckAll Button and CheckListBox
And you want when you click to CheckAll Button it will checks exactly all items in current TableLayoutPanel.
So try this code
class XForm : Form {
// create Dictionary to store Button and CheckListBox
IDictionary<Button, CheckListBox> map = new Dictionary<Button, CheckListBox> ();
// when you create new order (new TableLayoutPanel)
// just add map Button and CheckListBox to map
private void CreateOrder () {
var panel = new Panel ();
panel.Size = new System.Drawing.Size (360, 500);
panel.BorderStyle = BorderStyle.FixedSingle;
panel.Name = "panel";
var table = new TableLayoutPanel ();
var checklistBox = new CheckedListBox ();
var button = new Button () { Text = "CheckAll" };
table.Controls.Add (button, 1, 4);
button.Name = "b1";
button.Click += new EventHandler (CheckAll_Click);
button.AutoSize = true;
map[button] = checklistBox;
}
// and on event handle
private void CheckAll_Click (object sender, EventArgs e) {
var buttonClicked = (Button) sender;
var c = map[buttonClicked];
if (c == null) return;
for (int i = 0; i < c.Items.Count; i++)
{
c.SetItemChecked(i, true);
}
}
}
And dont for get remove it from map when remove the order.
Hope it helps
Related
This is a C# web form project I am starting with after a long time away from IDE coding...
I am trying to make a simple custom dialog box class. This is my code.
public static class Dialogo
{
public static int show ()
{
Form dialogo = new Form();
dialogo.Width = 300;
dialogo.Height = 300;
Button btnSim = new Button() { Text = "Sim", Left = 30, Width = 100 };
Button btnNao = new Button() { Text = "Não", Left = 150, Width = 100 };
dialogo.Controls.Add(btnSim);
dialogo.Controls.Add(btnNao);
dialogo.ShowDialog();
// the following two lines are the problematic ones
btnSim += new EventHandler(btnSim_Click);
btnNao += new EventHandler(btnNao_Click);
return -1;
}
}
It's underlining the text within parenthesis and the message says:
The name btnSim_Click' does not exist in the current context
The problem is that I tried to add the following in my code but it doesn't let me put it anywhere (it always says that is something wrong):
private int btnNao_Click (object sender, EventArgs e)
{
return 0;
}
private int btnSim_Click (object sender, EventArgs e)
{
return 1;
}
My objective is that each of the both buttons btnSim and btnNao return a different value (say 1 and 0).
What am I doing wrong?
EventHandler is a delegate for a method that returns void.
Your methods return int.
Try something like this:
public static int show()
{
int returnValue = -1;
using (Form dialogo = new Form())
{
dialogo.Width = 300;
dialogo.Height = 300;
Button btnSim = new Button() { Text = "Sim", Left = 30, Width = 100 };
Button btnNao = new Button() { Text = "Não", Left = 150, Width = 100 };
dialogo.Controls.Add(btnSim);
dialogo.Controls.Add(btnNao);
btnSim.Click += (s, e) => { returnValue = 0; dialogo.DialogResult = DialogResult.OK; };
btnNao.Click += (s, e) => { returnValue = 1; dialogo.DialogResult = DialogResult.OK; };
dialogo.Disposed += (s, e) =>
{
btnSim?.Dispose();
btnSim = null;
btnNao?.Dispose();
btnNao = null;
};
dialogo.ShowDialog();
}
return returnValue;
}
Background
I create a set of linklabel and label controls using a loop that uses data from a database as there content (Text).
Question
How do I then remove or change there visibility?
What I would Like to Happen?
On a button click event, I would like all of the link's and linklabel's text properties to be set to either null, or their visibility properties to be set as false.
Code
private void getInfoStationID()
{
//SQL Connection Stuff
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
Linklabel.Text = ds.Tables[0].Rows[i] ["code"].ToString();
Linklabel.Height = 15;
Linklabel.Width = 50;
Linklabel.AutoSize = true;
Linklabel.Location = new Point(10, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(Linklabel);
// Add an event handler to do something when the links are clicked.
Linklabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
Label label1 = new Label();
label1.Text = ds.Tables[0].Rows[i]["name"].ToString();
label1.Height = 15;
label1.Width = 70;
label1.Location = new Point(100, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label1);
Label label3 = new Label();
label3.Text = ds.Tables[0].Rows[i]["toc"].ToString();
label3.Height = 15;
label3.Width = 50;
label3.Location = new Point(240, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label3);
}
}
private void clearAllBtn_Click(object sender, EventArgs e)
{
//Would like this to clear all previously drawn labels and linklabels
}
Simply add the dynamic controls to a List so you have a quick reference to them:
// out at CLASS/FORM level:
private List<Control> MyControls = new List<Control>();
// ... some method ...
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
MyControls.Add(Linklabel);
// ... rest of your code ...
Label label1 = new Label();
MyControls.Add(label1);
// ... rest of your code ...
Label label3 = new Label();
MyControls.Add(label3);
// ... rest of your code ...
}
Now you can use that List from somewhere else:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Visible = false; // or something else
}
}
*Don't forget to dispose of those controls and empty the list if you decide to create a new set of dynamic controls. If you want to completely get rid of them:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Dispose();
}
MyControls.Clear();
}
You can loop through all controls on a certain tabpage. You could use a open generic function to make the code nice and clean. Like this:
private void HideControls<TControl>(Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
And use it like this:
private void button1_Click(object sender, EventArgs e)
{
this.HideControls<Label>(tabControl1.TabPages[0]);
this.HideControls<LinkLabel>(tabControl1.TabPages[0]);
}
You could even refactor this to a nice extension method:
public static class ControlExtensions
{
public static void HideControlsOfType<TControl>(this Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
}
and use like:
this.tabControl1.TabPages[0].HideControlsOfType<Label>();
I need to dynamically create buttons with labels under them in a flowLayoutPanel when i drop a file onto the form. But how do I set the label position to be under the button since the FLP is arranging the controls by itself.. ?
What I've tried:
void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach (string s in fileList)
{
Button button = new Button();
button.Click += new EventHandler(this.button_Click);
fl_panel.Controls.Add(button);
Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
Bitmap bmp = icon.ToBitmap();
button.BackgroundImage = bmp;
button.Width = 60;
button.Height = 75;
button.FlatStyle = FlatStyle.Flat;
button.BackgroundImageLayout = ImageLayout.Stretch;
int space = 5;
int Yy = button.Location.Y;
int Xx = button.Location.X;
Label label = new Label();
label.Location = new Point(Yy + space, Xx);
//label.Margin.Top = button.Margin.Bottom;
fl_panel.Controls.Add(label);
}
}
The best idea I know of is to implement a custom control that contains both a button and a label that are arranged correctly. Then add the custom control to the FlowLayoutPanel.
public class CustomControl:Control
{
private Button _button;
private Label _label;
public CustomControl(Button button, Label label)
{
_button = button;
_label = label;
Height = button.Height + label.Height;
Width = Math.Max(button.Width, label.Width);
Controls.Add(_button);
_button.Location = new Point(0,0);
Controls.Add(_label);
_label.Location = new Point(0, button.Height);
}
}
You can then add to it like this:
for (int i = 0; i < 10; i++)
{
CustomControl c = new CustomControl(new Button {Text = "Button!"}, new Label {Text = "Label!"});
fl_panel.Controls.Add(c);
}
EDIT:
If you want to listen to button events, try this:
for (int i = 0; i < 10; i++)
{
var button = new Button {Text = "Button " + i};
CustomControl c = new CustomControl(button, new Label {Text = "Label!"});
button.Click += buttonClicked;
fl_panel.Controls.Add(c);
}
...
private void buttonClicked(object sender, EventArgs e)
{
MessageBox.Show(((Button) sender).Text);
}
What am doing here is; making a UI to update values visually, will add more support for other types too. Possibly all types.
updateIcons this function is called everytime the controller is loaded, and has new values,names everytime.
countControls to keep track of controllers, so if can update values on clicks.
myP is the object that holds the values taken at runtime, user shuffles values by pressing tab from another screen
created radiobuttons groupboxes to allow radiobutton group to be managed.
properties all belong to one object. each property has few possible values like in my example, the enums.
now am kinda lost, not sure how to best do this, as now my rb_CheckedChanged is returning some kind of mess.
How do i do this the right way ? all together, i feel its somewhat the right approach At least.
I thought of making a dictionary of ? to use it at the checked event. not exactly sure how
private void updateIcons(List<Props> prop) {
countControls++;
locationY = 10;
int gbHeight;
foreach (var p in prop) {
radioButtonY = 10;
IType pType = p.Type;
if (pType is Enum) {
var myP = new MyProp(p, this);
GroupBox gb = new GroupBox();
gb.Location = new Point(nextLocationX,locationY);
nextLocationX += rbWidth+10;
gb.Name = "groupBox" + countControls;
gb.Text = "smthn";
var TypesArray = set here;
gbHeight = TypesArray.Length;
foreach (var type in TypesArray) {
getimagesPath(TypesArray);
RadioButton rb = new RadioButton();
rb.Appearance = Appearance.Button;
rb.Width = rbWidth;
rb.Height = rbHeight;
rb.Name = type.Name + countControls;
rb.Text = type.Name;
string path = imagePaths[type.Name];
Bitmap rbImage = new Bitmap(path);
rb.BackgroundImage = rbImage;
countControls++;
rb.Location = new Point(radioButtonX, radioButtonY);
if (myP.Value != null && type.Name.SafeEquals(myP.Value.ToString())) {
rb.Checked = true;
}
radioButtonY += rbHeight;
gb.Controls.Add(rb);
rb.CheckedChanged += rb_CheckedChanged;
}
gb.Height = rbHeight * gbHeight + 20;
gb.Width = rbWidth + 10;
Controls.Add(gb);
}
}
}
void rb_CheckedChanged(object sender, EventArgs e) {
RadioButton rb = (RadioButton)sender;
Control control = (Control)sender;
if (rb.Checked) {
MessageBox.Show("You have just checked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
var t = PropSeq;
}
else {
MessageBox.Show("you have just unchecked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
}
}
I think your code might be a little messed up and not the easiest to read. It looks plain invalid with not all closing braces present? Try the code below which will create two group boxes, each with five radio buttons. This should help you achieve what you are trying to do (full listing for a basic Form):
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CreateButton();
}
private void CreateButton()
{
// Add two group boxes
for (int groupCount = 1; groupCount < 3; groupCount++)
{
var groupBox = new GroupBox();
groupBox.Location = new Point(220 * (groupCount - 1), 10);
groupBox.Name = string.Format("groupBox{0}", groupCount);
groupBox.Text = string.Format("Group Box {0}", groupCount);
// Add some radio buttons to each
for (int buttonCount = 1; buttonCount < 6; buttonCount++)
{
var radioButton = new RadioButton();
radioButton.Width = 150;
radioButton.Location = new Point(10, 30 * buttonCount);
radioButton.Appearance = Appearance.Button;
radioButton.Name = string.Format("radioButton{0}", buttonCount);
radioButton.Text = string.Format("Dynamic Radio Button {0} - {1}", groupCount, buttonCount);
radioButton.CheckedChanged += radioButton_CheckedChanged;
// Add radio button to the group box
groupBox.Controls.Add(radioButton);
groupBox.Height += 20;
}
// Add group box to form
Controls.Add(groupBox);
}
}
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
// Get button and only show the selected (not now de-selected item)
var radioButton = (RadioButton)sender;
if (radioButton.Checked)
{
MessageBox.Show("You have just checked: " + radioButton.Text);
}
}
}
}
I m adding panel controls in a flowlayoutpanel dynamically as per the number of records in my table. i want to get id from each of the panels so that i can open a popup window on click event of panel. Any sugestions?
here is my code sample.
int id=0;
public void FillSearch()
{
var playerList = dianaDB.TblPlayers.Where(p => p.Status == "Active" & p.CancellationStatus == "Active" & p.Version == "Active").Select(p => p);
Panel pnlPlayer = new Panel();
foreach (var pl in playerList)
{
pnlPlayer = new Panel();
pnlPlayer.Size = new Size(153, 116);
pnlPlayer.BorderStyle = BorderStyle.FixedSingle;
pnlPlayer.Cursor = Cursors.Hand;
pnlPlayer.Click += new EventHandler(pbx_Click);
id=pl.Id;
}
}
private void pbx_Click(object sender, EventArgs e)
{
DlgSearchDetails newDlg = new DlgSearchDetails(id);
newDlg.ShowDialog();
}
You can store the ID of a panel in its Tag property.
pnlPlayer.Tag = id;
Then retrieve it later
private void pbx_Click(object sender, EventArgs e)
{
Panel p = sender as Panel;
if(p != null)
{
//TODO add error handling to ensure Tag contains an int
//...
DlgSearchDetails newDlg = new DlgSearchDetails((int)p.Tag);
newDlg.ShowDialog();
}
}
Assuming , you are asking about the WinForm
There is a tag property in each controls , ypou can utilize it.
public void FillSearch()
{
var playerList = dianaDB.TblPlayers.Where(p => p.Status == "Active" & p.CancellationStatus == "Active" & p.Version == "Active").Select(p => p);
Panel pnlPlayer = new Panel();
foreach (var pl in playerList)
{
pnlPlayer = new Panel();
pnlPlayer.Size = new Size(153, 116);
pnlPlayer.BorderStyle = BorderStyle.FixedSingle;
pnlPlayer.Cursor = Cursors.Hand;
pnlPlayer.Click += new EventHandler(pbx_Click);
pnlPlayer.Tag = pl.Id;
}
}
private void pbx_Click(object sender, EventArgs e)
{
var panle = sender as Panel;
if(panel!=null)
{
DlgSearchDetails newDlg = new DlgSearchDetails(panel.Tag);
newDlg.ShowDialog();
}
}