Adding a control in Datagridview - c#

How to add a control in DataGridView? Using Button event. For example i want to create a new a row and column in DataGridView, this i want to happen through button control. How can i do it?
I am using C#.net and MS-Access.

Your question doesn't match it's title. The title asks about controls but the question is about rows and columns, I'm ignoring the title and I'm assuming it's an unbound DataGridView.
This MSDN link shows how to add rows and this shows how to add columns.

Here is a piece of code for adding a control into the gridview.
private void addNewRowButton_Click(object sender, EventArgs e)
{
this.DataGridViewIssue.Rows.Add();//This line will add a new button contol into the grid
}
private void deleteRowButton_Click(object sender, EventArgs e)
{
if (this.DataGridViewIssue.SelectedRows.Count > 0 &&
this.DataGridViewIssue.SelectedRows[0].Index !=
this.DataGridViewIssue.Rows.Count - 1)
{
this.DataGridViewIssue.Rows.RemoveAt(
this.DataGridViewIssue.SelectedRows[0].Index);
}
}
private void SetupLayout()
{
this.Size = new Size(1055, 800);
addNewRowButton.Text = "Add Row";
addNewRowButton.Location = new Point(10, 10);
addNewRowButton.Click += new EventHandler(addNewRowButton_Click);
deleteRowButton.Text = "Delete Row";
deleteRowButton.Location = new Point(100, 10);
deleteRowButton.Click += new EventHandler(deleteRowButton_Click);
buttonPanel.Controls.Add(addNewRowButton);
buttonPanel.Controls.Add(deleteRowButton);
buttonPanel.Height = 50;
buttonPanel.Dock = DockStyle.Bottom;
this.Controls.Add(this.buttonPanel);
}

Related

Removing textbox/label on button click C#

I am trying to remove textboxes and labels one by one by pressing a button.
I have a list of textboxes called inputTextBoxes.
Here is the code for adding :
private void onClickAdd(object sender, EventArgs e)
{
inputTextBoxes = new List<TextBox>();
Label label1 = new Label();
label1.Name = "label1";
label1.Text = "w" + i;
label1.Location = new System.Drawing.Point(5, 10 + (20 * i));
label1.Size = new System.Drawing.Size(30, 20);
this.Controls.Add(label1);
TextBox text1 = new TextBox();
text1.Name = "text1";
text1.Location = new System.Drawing.Point(35, 10 + (20 * i));
text1.Size = new System.Drawing.Size(25, 20);
inputTextBoxes.Add(text1);
this.Controls.Add(text1);
i++;
}
For removing I am trying this :
private void onClickRemove(object sender, EventArgs e)
{
foreach(TextBox text1 in inputTextBoxes)
{
this.Controls.Remove(text1);
}
}
But it removes only the last textbox added,clicking againg on the button doesn't do anything.
You are constantly creating a new list in your OnClickAdd() method:
inputTextBoxes = new List<TextBox>();
Try to check if the inputTextBoxes is null and only then do this line of code. Otherwise, just let the rest of the code run.
Also, remember about clearing the inputTextBoxes list after the onClickRemove() method finishes removing textboxes/labels.
You want to remove only one TextBox at a time, why do you need a foreach loop? just grab the last or first TextBox and if it is not null remove it from the Controls:
private void onClickRemove(object sender, EventArgs e)
{
var textBoxToRemove = inputTextBoxes.LastOrDefault();
// or
// var textBoxToRemove = inputTextBoxes.FirstOrDefault();
if (textBoxToRemove != null)
{
this.Controls.Remove(textBoxToRemove);
inputTextBoxes.Remove(textBoxToRemove);
}
}
Make sure you remove it from inputTextBoxes also so the next time you will ask to remove a TextBox it will not try to remove it again and go on to the next one.
Edit
#Piotr Nowak has pointed one more problem you have, you allocate a new list for inputTextBox every time you add a new TextBox, you should allocate the list only once when you create your class.
Remove this from onClickAdd method:
inputTextBoxes = new List<TextBox>();
And use this when you declare the list as a field it your class:
private readonly inputTextBoxes = new List<TextBox>();

C# combobox with fonts using Datasource Visual Studio 2013

I have a form with a ComboBox on it. I would like to fill this with the available fonts on the system and make the user to select one of these options.
I looked for different approaches to achieving this and I used this question and the answer to load the ComboBox with all the fonts: Fill ComboBox with List of available Fonts
This is my code currently that works:
form.comboBox2.Items.Clear();
System.Drawing.Text.FontCollection fontcoll = new System.Drawing.Text.InstalledFontCollection();
foreach (FontFamily font in fontcoll.Families)
{
form.comboBox2.Items.Add(font.Name);
}
But now I am trying to use instead the DataSource property and I imported the System.Drawing.Text.InstalledFontCollection into my project as datasource.
Here is the code of the designer:
//
// comboBox2
//
this.comboBox2.DataSource = this.installedFontCollectionBindingSource;
this.comboBox2.FormattingEnabled = true;
this.comboBox2.Location = new System.Drawing.Point(16, 44);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(144, 21);
this.comboBox2.TabIndex = 9;
this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged);
Then in my initialization of the form, I have this to set selected the font name to Times New Roman as default:
form.comboBox2.Text = "Times New Roman"
I thought this would be enough to fill the ComboBox and select Times New Roman but apparently is not enough. It displays Times New Roman alright, but the box is empty.
What I would like to get help with:
1) How to make the datasource to populate the ComboBox?
2) Is there a simple way to force the user to select one of the entries from the box and not type in some other value that is not in the list (similarly to the "MatchRequired" property in VBA userforms)?
Thanks in advance.
You should first get a list of all installed font families and then set the list as DataSource of ComboBox. Also you can set DropDownStyle of combo box to DropDownList.
private void Form1_Load(object sender, EventArgs e)
{
this.comboBox1.DataSource = new InstalledFontCollection().Families;
this.comboBox1.DisplayMember = "Name";
this.comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
this.comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
}
You can get selected font family from SelectedValueof ComboBox. For example:
void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.comboBox1.SelectedValue != null)
this.Font = new Font((FontFamily)this.comboBox1.SelectedValue, this.Font.Size);
}
You can use :
private void Form1_Load(object sender, EventArgs e)
{
FontFamily[] fontArray = FontFamily.Families;
foreach (FontFamily font in fontArray)
{
comboBox1.Items.Add(font.Name);
}
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
}
With a property DropDownStyle, users are limited to choices in the list.
For example if you want to assign font with size 14 to the Label :
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label1.Font = new Font(comboBox1.Text , 14);
}

How to Remove Textbox control created dynamically in WPF Grid?

I am unable to remove the textbox which is created Dynamically using Combobox selected Item in Grid. if the selected value is not equal to "Other (describe)", i have to remove the textbox. I have this code..
private void btn_addnew_Click(object sender, RoutedEventArgs e)
{
ComboBox cmb=new ComboBox();
.....
cmb.SelectionChanged+= cmb_SelectionChanged;
.....
}
void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var txt = new TextBox();
if (e.AddedItems[0].ToString() == "Other (describe)")
{
var row = (int)((ComboBox)sender).Tag;
Grid.SetRow(txt, row);
Grid.SetColumn(txt, 1);
txt.Margin = new Thickness(10, 10, 0, 0);
grid_typeFixture.Children.Add(txt);
}
else
grid_typeFixture.Children.Remove(txt);
}
There is a risk of setting the Textbox names dynamically if it doesn't follow the namming rules (Example : Textbox name can not have white space), Instead you can use "Tag" property of the textbox while creating and search it whenever want to remove it.
Assign a name to your TextBox while creating, you can use RegisterName,
txt = new TextBox();
txt.Margin = new Thickness(10, 10, 0, 0);
txt.Name = "DynamicLine" + i;
RegisterName(txt.Name, txt);
Grid.SetRow(txt, i);
Grid.SetColumn(txt, 2);
grid_typeFixture.Children.Add(txt);
And you can remove like this, using FindName
txt = (TextBox)grid_typeFixture.FindName("lbl_DynamicLine" + row);
if (txt != null)
{
UnregisterName(txt.Name);
grid_typeFixture.Children.Remove(txt);
}

Docking/Displaying Mutiple DataGridViews with Splitters Programmatically

All, I want to build and display multiple DataGridView seperated by horizontol Splitters at runtime. To test out doing this I have created a test application with the following code
private void button1_Click(object sender, EventArgs e)
{
int i = 1;
List<DataGridView> DgvList = new List<DataGridView>()
{
new DataGridView(), new DataGridView()
};
foreach (DataGridView Dgv in DgvList)
{
Dgv.Parent = this.panelMain;
int verticalSize = (int)(panelMain.Height / DgvList.Count);
Dgv.Height = verticalSize;
Dgv.Dock = DockStyle.Top;
if (DgvList.Count > 1 && i < DgvList.Count)
{
Splitter tmpSplitter = new Splitter();
tmpSplitter.Parent = this.panelMain;
tmpSplitter.Dock = DockStyle.Top;
tmpSplitter.BringToFront();
tmpSplitter.Height = 8;
}
i++;
}
}
However, this is not displaying the Splitter
Can someone highlight the error of my ways?
Thanks for your time.
Drop this line:
tmpSplitter.BringToFront();
and splitter will show.
Note that you are displaying grids in reversed order - the first in list will be at bottom of the screen.

how do I host a control in a DataGridViewCell for displaying as well as editing?

I've seen How to: Host Controls in Windows Forms DataGridView Cells which explains how to host a control for editing a cell in a DataGridView. But how can I host a control for displaying a cell?
I need to display a file name and a button in the same cell. Our UI designer is a graphic designer not a programmer, so I have to match the code to what he's drawn, whether it's possible - or wise - or not. We're using VS2008 and writing in C# for .NET 3.5, if that makes a difference.
UPDATE: The 'net suggests creating a custom DataGridViewCell which hosts a panel as a first step; anyone done that?
As per your "UPDATE", creating a custom DataGridViewCell is the way this is done. I've done it, and it doesn't require that much modification from the example code available from the MSDN. In my case, I needed a bunch of custom editing controls, so I ended up inheriting from DataGridViewTextBoxCell and DataGridViewColumn. I inserted into my class (the one inherited from DataGridViewTextBoxCell) a new custom control which implemented IDataGridViewEditingControl, and it all just worked.
I suppose that in your case, you could write a PanelDataGridViewCell which would contain a control MyPanelControl which would inherit from Panel and implement IDataGridViewEditingControl.
Rather than use a datagridview, how about using a TableLayoutPanel instead. Create your control that has a label and a button and events and fill your layout panel with them. Your control becomes the cell so to speak. It doesn't take much to make the table layout panel to look like a datagridview, if that is the layout style you want.
There are two ways to do this:
1). Cast a DataGridViewCell to a certain cell type that exists. For example, convert a DataGridViewTextBoxCell to DataGridViewComboBoxCell type.
2). Create a control and add it into the controls collection of DataGridView, set its location and size to fit the cell that to be host.
See Zhi-Xin Ye's sample code below which illustrates the tricks:
private void Form_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("name");
for (int j = 0; j < 10; j++)
{
dt.Rows.Add("");
}
this.dataGridView1.DataSource = dt;
this.dataGridView1.Columns[0].Width = 200;
/*
* First method : Convert to an existed cell type such ComboBox cell,etc
*/
DataGridViewComboBoxCell ComboBoxCell = new DataGridViewComboBoxCell();
ComboBoxCell.Items.AddRange(new string[] { "aaa","bbb","ccc" });
this.dataGridView1[0, 0] = ComboBoxCell;
this.dataGridView1[0, 0].Value = "bbb";
DataGridViewTextBoxCell TextBoxCell = new DataGridViewTextBoxCell();
this.dataGridView1[0, 1] = TextBoxCell;
this.dataGridView1[0, 1].Value = "some text";
DataGridViewCheckBoxCell CheckBoxCell = new DataGridViewCheckBoxCell();
CheckBoxCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
this.dataGridView1[0, 2] = CheckBoxCell;
this.dataGridView1[0, 2].Value = true;
/*
* Second method : Add control to the host in the cell
*/
DateTimePicker dtp = new DateTimePicker();
dtp.Value = DateTime.Now.AddDays(-10);
//add DateTimePicker into the control collection of the DataGridView
this.dataGridView1.Controls.Add(dtp);
//set its location and size to fit the cell
dtp.Location = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Location;
dtp.Size = this.dataGridView1.GetCellDisplayRectangle(0, 3,true).Size;
}
MSDN Reference : how to host different controls in the same column in DataGridView control
Using the 1st method looks like this:
Using the 2nd method looks like this:
Additional info: Controls in the same DataGridView column dont render while initializing grid
Usually you should host controls in winfors forms datagridview cells as shown here
But if you need your control to be always visible, what you can do is make a custom column inheriting from DataGridViewImageColumn. Add the control to the datagridview. Set the DefaultCellStyle.Nullvalue of the control to a bitmap of the control you want always shown on the data gridview. Then using the cellMouseEnter event you can display and reposition the control to display over the image cell. This gives the appearance that your custom control is always visible without using as much resources as creating a new instance of your control for every row added to the datagridview. This will help performance quite a bit.
Here is what I did with my custom “AddRemove” usercontrol.
public class AddRemoveColumn : DataGridViewImageColumn
{
private AddRemove SelectionControl = null;
private Bitmap SelectionControlImage = null;
public AddRemoveColumn()
{
SelectionControl = new AddRemove();
}
#region Set Up Column
protected override void OnDataGridViewChanged()
{
base.OnDataGridViewChanged();
if (DataGridView != null)
{
Activate();
}
}
private void Activate()
{
SelectionControl.LostFocus += SelectionControl_LostFocus;
this.DataGridView.CellMouseEnter += DataGridView_CellMouseEnter;
this.DataGridView.BackgroundColorChanged += DataGridView_BackgroundColorChanged;
this.DataGridView.RowHeightChanged += DataGridView_RowHeightChanged;
SelectionControl.OnAddClicked += AddClicked;
SelectionControl.OnRemoveClicked += RemoveClicked;
this.DataGridView.Controls.Add(SelectionControl);
SelectionControl.Visible = false;
this.Width = SelectionControl.Width;
SelectionControl.BackColor = this.DataGridView.BackgroundColor;
this.DataGridView.RowTemplate.Height = SelectionControl.Height +1;
foreach (DataGridViewRow row in DataGridView.Rows)
{
row.Height = SelectionControl.Height+1;
}
SetNullImage();
}
#endregion
private void AddClicked(int RowIndex)
{
MessageBox.Show("Add clicked on index=" + RowIndex.ToString());
}
private void RemoveClicked(int RowIndex)
{
MessageBox.Show("Removed clicked on index=" + RowIndex.ToString());
}
private void SetNullImage()
{
if (SelectionControlImage != null)
{
SelectionControlImage.Dispose();
}
SelectionControlImage = new Bitmap(SelectionControl.Width, SelectionControl.Height);
SelectionControl.DrawToBitmap(SelectionControlImage, new Rectangle(0, 0, SelectionControlImage.Width, SelectionControlImage.Height));
this.DefaultCellStyle.NullValue = SelectionControlImage;
}
private void DataGridView_RowHeightChanged(object sender, DataGridViewRowEventArgs e)
{
if (e.Row.Height <= 40)
{
e.Row.Height = 40;
}
SelectionControl.Visible = false;
SetPosition(Index, e.Row.Index);
}
private void DataGridView_BackgroundColorChanged(object sender, EventArgs e)
{
SelectionControl.BackColor = this.DataGridView.BackgroundColor;
SetNullImage();
}
private void SelectionControl_LostFocus(object sender, EventArgs e)
{
SelectionControl.Visible = false;
}
private void SetPosition(int ColumnIndex, int RowIndex)
{
Rectangle celrec = this.DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);//.Rows[e.RowIndex].Cells[e.ColumnIndex].GetContentBounds();
int x_Offet = (celrec.Width - SelectionControl.Width)/ 2;
int y_Offet = (celrec.Height - SelectionControl.Height)/2;
SelectionControl.Location = new Point(celrec.X + x_Offet, celrec.Y + y_Offet);
SelectionControl.Visible = true;
SelectionControl.RowIndex = RowIndex;
}
private void DataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == this.Index)
{
SetPosition(e.ColumnIndex, e.RowIndex);
}
}
}

Categories