I'm creating TextBoxes at runtime and add an EventHandler to eac, but I can only move the last one created, when I try to move a previous one, it disappears.
This is my code:
int Naslov_rnd;
TextBox tb;
private void Naslov_p_Click(object sender, EventArgs e)
{
Naslov_rnd++;
tb = new TextBox();
VizitKartica.SuspendLayout();
tb.Location = new Point(0, 0);
tb.Multiline = true;
tb.Size = new Size(200, 20);
tb.BorderStyle = BorderStyle.None;
tb.BackColor = Color.DodgerBlue;
tb.ForeColor = Color.White;
tb.Name = "Naslov_" + Naslov_rnd.ToString(); ;
tb.Text = "Dodajte Vaš naslov";
tb.Font = new Font("Microsoft Sans Serif", 12);
VizitKartica.Controls.Add(tb);
elementi_lista.AddItem(tb.Name);
VizitKartica.ResumeLayout(true); Controls collection
tb.MouseMove += new MouseEventHandler(tb_MouseMove);
tb.MouseDown += new MouseEventHandler(tb_MouseDown);
}
protected void tb_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
tb.Left = e.X + tb.Left;
tb.Top = e.Y + tb.Top;
}
}
protected void tb_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point MouseDownLocation = e.Location;
}
}
As #LarsTech said, you cannot make one TextBox object point to all of the TextBoxes that will be created, a simple and effective solution to this is to use the sender object.
The EventHandler provides you with an argument wich will get passed to the method, and it will point to the control that caused the event to be fired.
Since we know that all the TextBoxes are sharing the same event and they are all TextBoxes, we can type-cast the sender object to the TextBox class and then use it.
Here is how :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int Naslov_rnd;
private void button1_Click(object sender, EventArgs e)
{
Naslov_rnd++;
TextBox tb = new TextBox();
VizitKartica.SuspendLayout();
tb.Location = new Point(0, 0);
tb.Multiline = true;
tb.Size = new Size(200, 20);
tb.BorderStyle = BorderStyle.None;
tb.BackColor = Color.DodgerBlue;
tb.ForeColor = Color.White;
tb.Name = "Naslov_" + Naslov_rnd.ToString();
tb.Text = "Dodajte Vaš naslov";
tb.Font = new Font("Microsoft Sans Serif", 12);
VizitKartica.Controls.Add(tb);
VizitKartica.ResumeLayout(true);
tb.MouseMove += new MouseEventHandler(tb_MouseMove);
tb.MouseDown += new MouseEventHandler(tb_MouseDown);
}
protected void tb_MouseMove(object sender, MouseEventArgs e)
{
TextBox tb2 = (TextBox) sender;
if (e.Button == MouseButtons.Left)
{
tb2.Left = e.X + tb2.Left;
tb2.Top = e.Y + tb2.Top;
}
}
protected void tb_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point MouseDownLocation = e.Location;
}
}
}
Hope that helped you and what you are looking for.
Related
I have an action for my button in c# Winform like this:
private void btnAction_Click(object sender, EventArgs e)
{
TextBox tbxdg = new TextBox();
tbxdg.Name = "tbx_DG" + cx.ToString();
tbxdg.Location = new Point(508, 12 + (40 * cx));
tbxdg.Size = new Size(200, 24);
tbxdg.Font = new Font("Tahoma", 10);
panel2.Controls.Add(tbxdg);
cx++;
}
Now I want to get text from the textbox that i've created by clicking my button. I've tried call the textbox by the name that i given to it in the button click action but it's not working.
u can try this:
var textBoxText = panel2.Controls.Find("name of textbox", false).First().Text;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int cx = 0;
private void button1_Click(object sender, EventArgs e)
{
TextBox tbxdg = new TextBox();
tbxdg.Name = "tbx_DG" + cx.ToString();
tbxdg.Location = new Point(0, 0 + (40 * cx));
tbxdg.Size = new Size(200, 24);
tbxdg.Font = new Font("Tahoma", 10);
panel1.Controls.Add(tbxdg);
cx++;
}
private void button2_Click(object sender, EventArgs e)
{
label1.Text = string.Empty;
foreach (TextBox tb in panel1.Controls)
{
label1.Text += $"{tb.Name} - {tb.Text}\n";
}
}
}
Demo
Instead of searching the control name in the panel, another approach is to add all the dynamic text boxes to global List<TextBox>
Please read comments inside the example:
private int cx;
private List<TextBox> DynamicTextBoxesList = new List<TextBox>();
private void btnAction_Click(object sender, EventArgs e)
{
TextBox tbxdg = new TextBox();
tbxdg.Name = "tbx_DG" + cx.ToString();
tbxdg.Location = new Point(508, 12 + (40 * cx));
tbxdg.Size = new Size(200, 24);
tbxdg.Font = new Font("Tahoma", 10);
panel2.Controls.Add(tbxdg);
// add to list
DynamicTextBoxesList.Add(tbxdg);
cx++;
}
// button event for example how to use DynamicTextBoxesList
private void btnExampleFoaccesingTextBoxes_Click(object sender, EventArgs e)
{
if (DynamicTextBoxesList.Count > 0)
{
foreach (TextBox t in DynamicTextBoxesList)
{
MessageBox.Show(t.Text);
}
// or you can find by name for example you need cx=1:
var txtbox = DynamicTextBoxesList.Where(x => x.Name == "tbx_DG1").FirstOrDefault();
if (txtbox != null)
{
MessageBox.Show(txtbox.Text);
}
}
}
I have a bounded DataGridView. How can I add a button in one field with data? I will attach a screenshot of how I see it. Do you have any recommendations on this?
it's WinForms and I think that I need to write a custom column type.
I don't think the standard DataGridViewColumn subclasses provide what you're after.
It can be done, though: you will have to create your own custom Control (I guess a TextBox with a Button right next to it), and the appropriateDataGridViewColumn and DataGridViewCell subclasses to host your custom control.
Follow the documentation for further details.
Of course, the alternative would be using third-party, smarter grids.
Create custom column:
class TextAndButtonControl : UserControl
{
private TextBox textbox1;
private Button button1;
public TextAndButtonControl()
{
this.textbox1 = new TextBox();
this.Controls.Add(this.textbox1);
this.button1 = new Button();
this.Controls.Add(this.button1);
this.RenderControl();
this.button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hi");
}
public string Text
{
get { return this.textbox1.Text; }
set { this.textbox1.Text = value; }
}
public string ButtonText
{
get { return this.button1.Text; }
set { this.button1.Text = value; }
}
public void RenderControl()
{
this.textbox1.Location = new Point(0, 0);
this.textbox1.Width = 2 * this.Width / 3;
this.textbox1.Height = this.Height;
this.button1.Location = new Point(2 * this.Width / 3, 0);
this.button1.Width = this.Width / 3;
this.button1.Height = this.Height;
}
}
Add the control in the following way
private void Form1_Load(object sender, EventArgs e)
{
TextAndButtonControl bcol = new TextAndButtonControl();
bcol.Text = "Button Column ";
bcol.ButtonText = "Click Me";
bcol.Name = "btnClickMe";
bcol.RenderControl();
dgMainGrid.Controls.Add(bcol);
}
There is a DataGridViewButtonColumn-Type (Or if you just want a single Cell as Button -> DataGridViewButtonCell-Type).
You could create the DataGridButtonColumn and then add it to your DataGridView:
DataGridViewButtonColumn tempBtnColumn = new DataGridViewButtonColumn();
tempBtnColumn.HeaderText = "Button";
tempBtnColumn.Text = "Button-Text";
tempBtnColumn.Name = "Button-Name";
tempBtnColumn.UseColumnTextForButtonValue = true;
Grid.Columns.Add(tempBtnColumn);
//or if you want a specified position for the Grid:
Grid.Columns.Insert(0, tempBtnColumn);
Update
Here is an update, you could give the ButtonCell the Value you want and then read that with CurrentCell.Value (here is a example, hope it's understandable):
private void ButtonCellWithValue()
{
DataGridViewButtonCell dgvbc = new DataGridViewButtonCell();
dgvbc.Value = "1";
DataGridViewRow dgvr = new DataGridViewRow();
dgvr.Cells.Add(dgvbc);
dataGridView1.Rows.Add(dgvr);
dgvbc = new DataGridViewButtonCell();
dgvbc.Value = "2";
dataGridView1.Rows[0].Cells[1] = dgvbc;
GridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);
}
void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (((DataGridView)sender).CurrentCell.Value == "1")
{
MessageBox.Show("Super");
}
else if (((DataGridView)sender).CurrentCell.Value == "2")
{
MessageBox.Show("Better");
}
}
Thank a lot #RavirajPalvankar.
If somebody will need, I will write the code here, because cann't write it to Ravuraj's comment, because it's long:
Use the class as Raviraj write:
class TextAndButtonControl : UserControl
{
private TextBox textbox1;
private Button button1;
public TextAndButtonControl()
{
this.textbox1 = new TextBox();
this.Controls.Add(this.textbox1);
this.button1 = new Button();
this.Controls.Add(this.button1);
this.renderControl();
this.button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Click! The value is:" + this.Text);
}
public string Text
{
get { return this.textbox1.Text; }
set { this.textbox1.Text = value; }
}
public string ButtonText
{
get { return this.button1.Text; }
set { this.button1.Text = value; }
}
public void renderControl()
{
this.textbox1.Location = new Point(0, 0);
this.textbox1.Width = 2 * this.Width / 3;
this.textbox1.Height = this.Height;
this.button1.Location = new Point(2 * this.Width / 3, 0);
this.button1.Width = this.Width / 3;
this.button1.Height = this.Height;
}
}
then in main Form:
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("col1");
dt.Columns.Add("col2");
for (int j = 0; j < 20; j++)
{
dt.Rows.Add("col1" + j.ToString(), "col2" + j.ToString());
}
this.dataGridView1.DataSource = dt;
this.dataGridView1.Columns[0].Width = 150;
this.txbtnControl = new TextAndButtonControl();
this.txbtnControl.Visible = false;
this.dataGridView1.Controls.Add(this.txbtnControl);
//Handle the cellbeginEdit event to show the usercontrol in the cell while editing
this.dataGridView1.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView1_CellBeginEdit);
}
TextAndButtonControl txbtnControl;
void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.RowIndex != this.dataGridView1.NewRowIndex)
{
Rectangle rect = this.dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
this.txbtnControl.Location = rect.Location;
this.txbtnControl.Size = rect.Size;
this.txbtnControl.Text = this.dataGridView1.CurrentCell.Value.ToString();
this.txbtnControl.ButtonText = "...";
this.txbtnControl.renderControl();
this.txbtnControl.Visible = true;
}
}
I want to show a inherited text box control on mouse over on the form. But text is not displayed. Below is my code.
private ChartCalloutBox m_calloutbox = null;
public Form2()
{
InitializeComponent();
this.MouseMove += Form2_MouseMove;
}
void Form2_MouseMove(object sender, MouseEventArgs e)
{
if (m_calloutbox == null)
{
m_calloutbox = new ChartCalloutBox();
}
m_calloutbox.Location = e.Location;
m_calloutbox.Show();
}
internal class ChartCalloutBox : TextBox
{
public ChartCalloutBox()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.SuspendLayout();
this.Location = new System.Drawing.Point(350, 170);
this.ClientSize = new System.Drawing.Size(130, 40);
this.Size = new System.Drawing.Size(130, 40);
this.BackColor = System.Drawing.Color.Black;
this.ForeColor = System.Drawing.Color.Brown;
this.Name = "CalloutBox";
this.Text = "Callout Rect";
this.ResumeLayout(false);
//
}
}
Any one help on this how to show the text box on mouse over. and the text box place should be change based on the mouse position.
Thanks,
Bharathi.
Add your control to controls collection.
Code should be like
void Form2_MouseMove(object sender, MouseEventArgs e)
{
if (m_calloutbox == null)
{
m_calloutbox = new ChartCalloutBox();
this.Controls.Add(m_calloutbox);
}
m_calloutbox.Location = e.Location;
}
I am adding a moveable PictureBox control at runtime in my application as shown in the code below. I would like that when I double click on the PictureBox control, which is added at runtime, a new window opens. I tried to add an event of double click, but it's not working. Can you guide me on this how can I open a new window when double clicking on the added PictureBox control at runtime?
PictureBox[] PicArray;
PictureBox pb = new PictureBox();
pb.BackgroundImage = Image.FromFile(#"C:\Esp_Calculator\ESP Planner\1206570458690641104johnny_automatic_bridge.svg.med.png");
pb.Location = new Point(0, 0);
pb.BackColor = Color.Transparent;
pb.BackgroundImageLayout = ImageLayout.Zoom;
pb.MouseDown += new MouseEventHandler(this.drawArea_MouseDown);
pb.MouseMove += new MouseEventHandler(this.drawArea_MouseMove);
pb.MouseDoubleClick += pb_MouseDoubleClick;
drawArea.Controls.Add(pb);
List<PictureBox> lblList = new List<PictureBox>();
foreach (Control d in Controls)
if (d is PictureBox)
lblList.Add((PictureBox)d);
PicArray = lblList.ToArray();
private void drawArea_MouseDown(object sender, MouseEventArgs e)
{
move = e.Location;
}
private void drawArea_MouseMove(object sender, MouseEventArgs e)
{
Control Pb = (Control)sender;
if ((Control.ModifierKeys & Keys.Control) != 0)
{
if ((Control.MouseButtons & MouseButtons.Left) != 0)
{
Pb.Left += e.X - move.X;
Pb.Top += e.Y - move.Y;
}
}
}
void pb_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
Editor ed = new Editor();
ed.Show();
}
I got it. DoubleClick does the trick instead of MouseDoubleClick Event. Thanks . Here is the answer and working code:
PictureBox[] PicArray;
PictureBox pb = new PictureBox();
pb.BackgroundImage = Image.FromFile(#"C:\Esp_Calculator\ESP Planner\1206570458690641104johnny_automatic_bridge.svg.med.png");
pb.Location = new Point(0, 0);
pb.BackColor = Color.Transparent;
pb.BackgroundImageLayout = ImageLayout.Zoom;
pb.MouseDown += new MouseEventHandler(this.drawArea_MouseDown);
pb.MouseMove += new MouseEventHandler(this.drawArea_MouseMove);
pb.DoubleClick += pb_DoubleClick;
drawArea.Controls.Add(pb);
List<PictureBox> lblList = new List<PictureBox>();
foreach (Control d in Controls)
if (d is PictureBox)
lblList.Add((PictureBox)d);
PicArray = lblList.ToArray();
private void drawArea_MouseDown(object sender, MouseEventArgs e)
{
move = e.Location;
}
private void drawArea_MouseMove(object sender, MouseEventArgs e)
{
Control Pb = (Control)sender;
if ((Control.ModifierKeys & Keys.Control) != 0)
{
if ((Control.MouseButtons & MouseButtons.Left) != 0)
{
Pb.Left += e.X - move.X;
Pb.Top += e.Y - move.Y;
}
}
}
void pb_DoubleClick(object sender, System.EventArgs e)
{
Editor ed = new Editor();
ed.Show();
}
I want to deleting image inside picturebox ( its autogenerated) that selected mouse click, So I can delete it with delete key or maybe contextmenu...
Here the code:
private void button1_Click(object sender, EventArgs e)
{
string theimage = AppDomain.CurrentDomain.BaseDirectory + #"allimages";
string[] images = Directory.GetFiles(theimage, "*.png");
int aa;
for (aa = 1; aa < images.Count(); aa++)
{
PictureBox myPicBox = new PictureBox();
myPicBox.Location = new Point(7, 240);
myPicBox.Width = 100;
myPicBox.Height = 77;
myPicBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
myPicBox.Margin = new Padding(3, 3, 3, 3);
myPicBox.Visible = true;
myPicBox.Image = new Bitmap(images[aa]);
this.flowLayoutPanel1.Controls.Add(myPicBox);
//myPicBox.Click += new EventHandler(curPb_Click);
//myPicBox.MouseUp += new MouseEventHandler(myPicBox_MouseUp);
myPicBox.MouseDown += new MouseEventHandler(myPicBox_MouseDown);
myPicBox.MouseLeave += new EventHandler(mmm_Leave);
}
}
//private PictureBox senderAsPictureBox = null;
private void mmm_Leave(object sender, EventArgs e)
{
PictureBox senderAsPictureBox = sender as PictureBox;
senderAsPictureBox.BackColor = Color.Empty;
}
private void myPicBox_MouseDown(object sender, MouseEventArgs e)
{
PictureBox senderAsPictureBox = sender as PictureBox;
MessageBox.Show(senderAsPictureBox.ToString());
senderAsPictureBox.BackColor = Color.AliceBlue;
}
Here what I want to do
LOGIC:
User selecting image thumb inside picturebox -> When USER press [delete] keys -> delete the selected image
I don't get your problem.
If you want to clear it use this:
senderAsPictureBox.Image = null;
senderAsPictureBox.Invalidate();
EDIT:
After you set the image, set the name of the control to the imagepath:
myPicBox.Name = images[aa].ToString();
Also create a new Eventhandler to handle your KeyDownEvent
myPicBox.PreviewKeyDown += new reviewKeyDownEventHandler(myPicBox_PreviewKeyDown);
With this method:
void myPicBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
PictureBox senderAsPictureBox = sender as PictureBox;
File.Delete(senderAsPictureBox.Name);
}
In your MouseDownHandlerMethod focus your control with:
senderAsPictureBox.Focus();
Found solution from here Get Picturebox Path and SubNatural answers
So, I'll leave the code here for who may need it
private void button1_Click(object sender, EventArgs e)
{
string theimage = AppDomain.CurrentDomain.BaseDirectory + #"allimages";
string[] images = Directory.GetFiles(theimage, "*.png");
int aa;
for (aa = 1; aa < images.Count(); aa++)
{
PictureBox myPicBox = new PictureBox();
myPicBox.Location = new Point(7, 240);
myPicBox.Width = 100;
myPicBox.Height = 77;
myPicBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
myPicBox.Margin = new Padding(3, 3, 3, 3);
myPicBox.Visible = true;
FileStream fs = new FileStream(images[aa], FileMode.Open, FileAccess.Read);
myPicBox.Image = Image.FromStream(fs);
myPicBox.Name = images[aa];
fs.Close();
this.flowLayoutPanel1.Controls.Add(myPicBox);
//myPicBox.Click += new EventHandler(curPb_Click);
//myPicBox.MouseUp += new MouseEventHandler(myPicBox_MouseUp);
myPicBox.MouseDown += new MouseEventHandler(myPicBox_MouseDown);
myPicBox.MouseLeave += new EventHandler(mmm_Leave);
myPicBox.PreviewKeyDown += new PreviewKeyDownEventHandler(myPicBox_PreviewKeyDown);
}
}
private void myPicBox_MouseDown(object sender, MouseEventArgs e)
{
PictureBox senderAsPictureBox = sender as PictureBox;
senderAsPictureBox.Focus(); // binding for clicking
senderAsPictureBox.BackColor = Color.AliceBlue;
}
void myPicBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
PictureBox senderAsPictureBox = sender as PictureBox;
if (e.KeyCode == Keys.Delete)
senderAsPictureBox.Image = null;
senderAsPictureBox.Invalidate();
senderAsPictureBox.Dispose();
File.Delete(senderAsPictureBox.Name);
}
Thanks for everyone for helping me... :) especially for #SubNatural