I create a custom control inside a tab control which contains a flowLayoutPanel on every tab by dragging files on the selected tab. I have a context menu to rename and delete tab pages, but i want also to be able to delete a button created when I right click on it and select "remove"... I cannot find a way to delete only the selected button..
This is what I have to create the buttons:
public void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach (string s in fileList)
{
var button = new Button();
path_app = String.Format("{0}", s);
string filename = path_app;
file_name = Path.GetFileName(path_app);
Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
Bitmap bmp = icon.ToBitmap();
CustomControl custom_btn = new CustomControl(button, new Label { Text = file_name });
button.Tag = path_app;
button.BackgroundImage = bmp;
button.BackgroundImageLayout = ImageLayout.Stretch;
FlowLayoutPanel selectedFLP = (FlowLayoutPanel)tabControl1.SelectedTab.Controls[0];
selectedFLP.Controls.Add(custom_btn);
button.Click += new EventHandler(button_Click);
ContextMenu cm2 = new ContextMenu();
cm2.MenuItems.Add("Remove", new EventHandler(rmv_btn_click));
custom_btn.ContextMenu = cm2;
}
}
private void rmv_btn_click(object sender, System.EventArgs e)
{
foreach (Control X in fl_panel.Controls)
{
fl_panel.Controls.Remove(X);
}
}
How do I get the button which I right click on it as sender in the rmv_btn_click event to know which one to delete?
If I understand what you mean, You need to use something like this.
private void rmv_btn_click(object sender, System.EventArgs e)
{
fl_panel.Controls.Remove(sender as Button);
}
private void rmv_btn_click(object sender, System.EventArgs e)
{
Button btn = new Button();
Label lbl = new Label();
CustomControl cst_btn = new CustomControl(btn, lbl);
cst_btn = sender as CustomControl;
DialogResult dialogResult = MessageBox.Show("Are you sure that you want to remove this object?", "Remove object", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
cst_btn.Dispose();
}
else if (dialogResult == DialogResult.No)
{
//do nothing
}
}
public EventHandler handlerGetter(CustomControl button)
{
return (object sender, EventArgs e) =>
{
rmv_btn_click(button, e);
};
}
Related
I have Dynamically generated panels on my Form, every panel has multiple controls including TextBoxes, ComboBoxes and Buttons. I want to catch their values on a "Save" Button which is not dynamically generated (its in the form). I'm getting the Values with this code:
private void GetPanelControls(object sender, EventArgs e)
{
Panel allpanels = sender as Panel;
panelname = ItemsIDSelected[panelnamecounter] + "p";
//"p" identifies Panel and there is a counter with a list
if (allpanels.Name == panelname)
{
foreach (Control item in allpanels.Controls)
{
if (item.Name == (ItemsIDSelected[panelcontrolcounter] + "t")) //"t" identifies TextBox
{
ItemsNameListforInsert.Add(item.Text);
panelcontrolcounter++; //Panel has multiple controls
}
panelnamecounter++; //There are multiple Panels
}
}
}
How can I call this event on my Button_Click Event??
Panel panelGroup = new System.Windows.Forms.Panel();
panelGroup.Click += new EventHandler(GetPanelControls);
This is how Im Generating Panels and its event.
you can try something like this
private void Button_Click(object sender, EventArgs e)
{
GetPanelControls(this, new EventArgs());
}
EDIT
What if we use a method for this without using panel click event, if you need you can call this method inside the panel click event
private void GetPanelControls()
{
foreach (Control formControl in this.Controls)
{
if (formControl is Panel)
{
string panelName = ItemsIDSelected[panelnamecounter] + "p";
if (formControl.Name == panelName)
{
foreach (Control item in formControl.Controls)
{
// Your Code
}
}
}
}
}
//Control create button
private void button1_Click(object sender, EventArgs e)
{
Panel pnl = new Panel();
pnl.Name = "pnltest";
pnl.Location = new Point(500, 200);
TextBox txt1 = new TextBox();
txt1.Name = "txttest";
txt1.Location = new Point(0 ,10);
pnl.Controls.Add(txt1);
ComboBox cmb = new ComboBox();
cmb.Location = new Point(0, 50);
cmb.Name = "cmbtest";
cmb.Items.Add("one");
cmb.Items.Add("two");
cmb.Items.Add("three");
pnl.Controls.Add(cmb);
Button btn = new Button();
btn.Name = "btntest";
btn.Text = "submit";
btn.Location = new Point(0, 75);
btn.Click += btn_Click;
pnl.Controls.Add(btn);
this.Controls.Add(pnl);
}
//control button click event
void btn_Click(object sender, EventArgs e)
{
foreach (Control frmcntrl in this.Controls)
{
if (frmcntrl is Panel)
{
if (frmcntrl.Name == "pnltest")
{
foreach (Control item in frmcntrl.Controls)
{
if (item is TextBox)
{
if (item.Name == "txttest")
{
MessageBox.Show(item.Text .ToString());
}
}
else if (item is ComboBox)
{
if (item.Name == "cmbtest")
{
MessageBox.Show(item.Text);
}
}
}
}
}
}
}
I have a tabControl and a flowLayoutPanel inside each tab.. When I drag and drop a file onto a tab it creates a button with the icon of the file dropped. But i have the option to create more tabs and I want to be able to drag files into the selected tab.. but the problem is the flowLayoutPanel when adding the button..
My code so far:
public Process myProcess = new Process();
FlowLayoutPanel fl_panel = new FlowLayoutPanel();
string path_app;
public Form1()
{
InitializeComponent();
//add the flowLayoutPanel on the first tab
fl_panel.Dock = DockStyle.Fill;
fl_panel.BringToFront();
tabPage1.Controls.Add(fl_panel);
this.DragEnter += new DragEventHandler(Form1_DragEnter);
this.DragDrop += new DragEventHandler(Form1_DragDrop);
}
void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
e.Effect = DragDropEffects.All;
}
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);
path_app = String.Format("{0}", s);
button.Tag = path_app;
string filename = path_app;
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;
}
}
private void button_Click(object sender, System.EventArgs e)
{
String path_app = ((sender as Button).Tag as String);
myProcess.StartInfo.FileName = path_app;
myProcess.Start();
}
private void add_tab_btn_Click(object sender, EventArgs e)
{
//Create new tab with FLP inside
string title = Convert.ToString(textBox1.Text);
TabPage new_TabPage = new TabPage(title);
fl_panel.Dock = DockStyle.Fill;
fl_panel.BringToFront();
new_TabPage.Controls.Add(fl_panel);
tabControl1.TabPages.Add(new_TabPage);
}
}
If I use fl_panel.Controls.Add(button); it adds the buttons fine, on the first tab, but if I create a new tab I don't know how to use tabControl.SelectedTab with the fl_panel.Controls.Add(button) to add the buttons correctly on the selected tab.
You have to create a new FlowLayoutPanel for every tab:
FlowLayoutPanel fl_panel = new FlowLayoutPanel();
...
new_TabPage.Controls.Add(fl_panel);
And then you can cast the first element of the TabPage to the FlowLayoutPanel and access the Controls from there:
FlowLayoutPanel selectedFLP = (FlowLayoutPanel)tabControl.SelectedTab.Controls[0];
...
I have a form with a tabControl and inside of each tab is a flowLayoutPanel where I can drag and drop files and a button is created for each dropped file. Afterwards when I click on a button, the file that i dropped should open. I have managed to do this for one file only.. My problem is how can I tell which button was clicked and to open the file/app stored in the path for each button.. How can I differentiate in the button_click event the clicked button and the path of the app to open?
Code for this part so far:
Process myProcess = new Process();
string path_app;
public Form1()
{
InitializeComponent();
this.DragEnter += new DragEventHandler(Form1_DragEnter);
this.DragDrop += new DragEventHandler(Form1_DragDrop);
}
void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
e.Effect = DragDropEffects.All;
}
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);
flowLayoutPanel1.Controls.Add(button);
path_app = String.Format("{0}", s);
}
}
private void button_Click(object sender, System.EventArgs e)
{
myProcess.StartInfo.FileName =path_app;
myProcess.Start();
}
Also my tabControl has the possibility to add new tabs but how can I get the selected tab and the inside flowLayoutPanel to know where to create the button?
And by the way, is there a problem of how I open the files? I understood that i have to take into consideration the working directory..
Thank you for your help!
You can utilize Tag property of the Button:
void Form1_DragDrop(object sender, DragEventArgs e)
{
foreach (String s e.Data.GetData(DataFormats.FileDrop))
{
Button button = new Button();
button.Click += new EventHandler(this.button_Click);
flowLayoutPanel1.Controls.Add(button);
path_app = String.Format("{0}", s);
// Add to Tag any data you want to pin to the button
button.Tag = path_app;
}
}
private void button_Click(object sender, System.EventArgs e)
{
// Obtain via Tag
String path_app = ((sender as Button).Tag as String);
myProcess.StartInfo.FileName = path_app;
myProcess.Start();
}
You could use button.Tag = "theFancyPath" and in the EventHandler cast the object sender as Button to access the Tag property.
If you need more then you could inherit from Button:
public class ButtonWithPathProperty : Button
{
public FileInfo PathToOpen { get; private set; }
public ButtonWithPathProperty(FileInfo path)
{
PathToOpen = path;
this.Click += new EventHandler(this.button_Click);
}
private void button_Click(object sender, System.EventArgs e)
{
var yourPath = this.PathToOpen;
}
}
This is not tested btw :)
I have created 5 text boxes in a button click event and i have to get the values in the text boxes when the dynamically generated button is clicked.
protected void Button1_Click(object sender, EventArgs e)
{
for(int i=0;i<5;i++)
{
HtmlGenericControl tr = new HtmlGenericControl("tr");
HtmlGenericControl td = new HtmlGenericControl("td");
HtmlGenericControl tdbtn = new HtmlGenericControl("td");
TextBox txt=new TextBox();
txt.ID="txt_"+i.ToString();
td.Controls.Add(txt);
Button btn=new Button();
btn.ID="btn_"+i.ToString();
btn.Click+=new EventHandler(btnpay_Click);
btn.Text="Pay";
tdbtn.Controls.Add(btn);
tr.Controls.Add(td);
tr.Controls.Add(tdbtn);
PlaceHolder1.Controls.Add(tr);
}
}
But i couldn't get the Values in the text boxes at btnpay_Click
protected void btnpay_Click(object sender, EventArgs e)
{
Button btn = new Button();
btn = sender as Button;
string[] splitvaues = btn.ID.Split('_');
string identity = splitvaues[1];
TextBox txt = new TextBox();
txt =PlaceHolder1.FindControl("txt_" + identity) as TextBox;
}
Can Anybody tell me a way to solve this problem?
Your problem is that FindControl doesn't recurse down the control tree. It only searches the controls directly in the ControlCollection of the container.
This method will find a control only if the control is directly
contained by the specified container; that is, the method does not
search throughout a hierarchy of controls within controls.
You need to write a recursive FindControl. Something like:
public static Control FindControlRecursive(this Control control, string id)
{
if (control == null || control.ID == id) return control;
foreach (var c in control.Controls)
{
var found = c.FindControlRecursive(id);
if (found != null) return found;
}
return null;
}
try this code.....
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
createcontrol();
}
}
private void createcontrol()
{
for (int i = 0; i < 5; i++)
{
HtmlGenericControl tr = new HtmlGenericControl("tr");
HtmlGenericControl td = new HtmlGenericControl("td");
HtmlGenericControl tdbtn = new HtmlGenericControl("td");
TextBox txt = new TextBox();
txt.ID = "txt_" + i.ToString();
td.Controls.Add(txt);
Button btn = new Button();
btn.ID = "btn_" + i.ToString();
btn.Click += new EventHandler(btnpay_Click);
btn.Text = "Pay";
tdbtn.Controls.Add(btn);
tr.Controls.Add(td);
tr.Controls.Add(tdbtn);
plh1.Controls.Add(tr);
}
}
protected void btnpay_Click(object sender, EventArgs e)
{
Button btn = new Button();
btn = sender as Button;
string[] splitvaues = btn.ID.Split('_');
string identity = splitvaues[1].ToString();
TextBox txt = new TextBox();
txt = plh1.FindControl("txt_" + identity) as TextBox;
string q = txt.Text;
}
protected void Button1_Click(object sender, EventArgs e)
{
createcontrol();
}
Here are all my classes.
MainForm = listview,
CustomerFrame = textboxes
When I compile my program, my MainForm appears with an empty listview, and when I press on the add button to insert an item, my CustomerFrame class appears. When writing in the textboxes and clicking ok, no item inserted in my listview (MainForm). Why?
Some code:
MainForm
using(var customerframe = new CustomerFrame())
{
if (customerframe.DialogResult == DialogResult.OK)
{
CustomerFiles.Contact contact = customerframe.GetContact();
CustomerFiles.Address address = customerframe.GetAddress();
CustomerFiles.Phone phone = customerframe.GetPhone();
CustomerFiles.Email email = customerframe.GetEmail();
//Items in my listview
listviewitem = new ListViewItem();
listviewitem.SubItems.Add(contact.FirstName);
listviewitem.SubItems.Add(contact.LastName);
listviewitem.SubItems.Add(phone.Home);
listviewitem.SubItems.Add(phone.Mobile);
listviewitem.SubItems.Add(address.Country);
listviewitem.SubItems.Add(address.ZipCode);
listviewitem.SubItems.Add(address.City);
listviewitem.SubItems.Add(address.Street);
listviewitem.SubItems.Add(email.Personal);
this.listView1.Items.Add(listviewitem);
}
}
MainForm
private void addToolStripMenuItem_Click_1(object sender, EventArgs e)
{
customerframe.Show();
CustomerManager cm = new CustomerManager();
}
CustomerFrame
private void btnOk_Click(object sender, EventArgs e)
{
MainForm main = new MainForm();
DialogResult = DialogResult.OK;
}
By the way, when I use
if (customerframe.ShowDialog() == DialogResult.OK)
this will make the CustomerFrame form appear before the MainForm (which I don't want) and it will insert item, but only once.
Why do you open ANOTHER main form from DialogBox? I think that you should remove this line.
MainForm main = new MainForm();
And add this
DialogResult = DialogResult.OK;
Close();
Argh, to simplify - code in ButtonOK should look like this:
private void btnOk_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
Close();
}
EDIT: response to new problem
First create new CustomerFrame, show it and wait for it to close; then transfer new data to your ListView. I believe that your add handler should look like this:
private void addToolStripMenuItem_Click_1(object sender, EventArgs e)
{
using(var customerframe = new CustomerFrame())
{
// I don't know what this line does
CustomerManager cm = new CustomerManager();
if (customerFrame.ShowDialog() == DialogResult.OK)
{
CustomerFiles.Contact contact = customerframe.GetContact();
CustomerFiles.Address address = customerframe.GetAddress();
CustomerFiles.Phone phone = customerframe.GetPhone();
CustomerFiles.Email email = customerframe.GetEmail();
//Items in my listview
listviewitem = new ListViewItem();
listviewitem.SubItems.Add(contact.FirstName);
listviewitem.SubItems.Add(contact.LastName);
listviewitem.SubItems.Add(phone.Home);
listviewitem.SubItems.Add(phone.Mobile);
listviewitem.SubItems.Add(address.Country);
listviewitem.SubItems.Add(address.ZipCode);
listviewitem.SubItems.Add(address.City);
listviewitem.SubItems.Add(address.Street);
listviewitem.SubItems.Add(email.Personal);
this.listView1.Items.Add(listviewitem);
}
}
}