I have list usrdetails that I'm using as my data source for my DataGridview.
Two questions:
How can I change the column type for the 3rd Column in my DataGridview from a DataGridTextBoxColumn to a DataGridComboBoxColumn?
Once I've changed the 3rd column to a ComboBox how would I populate with list of strings?
public class usrInfo
{
public string userID { get; set; }
public string username { get; set; }
public string group { get; set; }
public string seclev { get; set; }
public string isext { get; set; }
public usrInfo(string userID, string username, string group, string seclev, string isext)
{
this.userID = userID;
this.username = username;
this.group = group;
this.seclev = seclev;
this.isext = isext;
}
}
public static List<usrInfo> usrdetails = new List<usrInfo>();
private void Form5_Load(object sender, EventArgs e)
{
var comboColumn = new DataGridViewComboBoxColumn();
dataGridView1.DataSource = null;
dataGridView1.DataSource = usrdetails;
for (int i = 0; i < secgrps.Count; i++)
groups.Add(secgrps[i].ToString());
comboColumn.Name ="Security Group";
comboColumn.DataSource = groups;
dataGridView1.Columns.Insert(2, comboColumn);
usrdetails.Add(new usrInfo("domain\\userID", "User Name", "RIGSITE ONLY Wellsite Leader", "7", "Y"));
dataGridView1.Refresh();
if (usrdetails.Count > -1)
num_users = true;
}
You need to add a DataGridViewComboBoxColumn to your dataGridView1 control and assign its DataSource property to the collection of strings you want.
var myStringCollection = new[] {"String1", "String2", "String3"};
var comboColumn = new DataGridViewComboBoxColumn();
comboColumn.Name = "MyComboColumn";
comboColumn.DataSource = myStringCollection; //This sets the source of drop down items
Then insert it into your grid:
if (dataGridView1.Columns["MyComboColumn"] == null)
{
//The int value as first parameter of Insert() is the desired Column Index
dataGridView1.Columns.Insert(0, comboColumn);
}
Related
I work in Windows Forms. I have a combobox ('Departments' name) it contains a list of departments. By selecting a department in comboBox1(Staff), employees working in this department appear. But I can't select an employee, because they are not displayed
Code, filling in comboBox1(Staff). dataNames - dictionary(department name - array of employees)
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (Departaments.SelectedItem != null)
{
this.Staff.Items.Clear();
var dataNames = DataForComdodox.ArrNames(Departaments.SelectedItem.ToString());
this.Staff.Items.AddRange(dataNames);
}
}
Code in Form1.Designer - comboBox1(Staff)
this.Staff.DrawMode = System.Windows.Forms.DrawMode.Normal;
this.Staff.FormattingEnabled = true;
this.Staff.Items.AddRange(new object[] {
});
this.Staff.Location = new System.Drawing.Point(374, 84);
this.Staff.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.Staff.Name = "Staff";
this.Staff.Size = new System.Drawing.Size(158, 21);
this.Staff.TabIndex = 0;
this.Staff.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
I tried to change Staff.SelectedIndex = 0, after I fill comboBox1(Staff) with values, but in the end, when choosing a department, an employee was selected automatically with an index of 0
If var dataNames = DataForComdodox.ArrNames(xx) returns a list or array of class employees, you could override the ToString() in the employee class.
public class Employee
{
public int EmpId { get; set; }
public string EmpName { get; set; }
public string DeptName { get; set; }
public override string ToString()
{
return $"{this.EmpId}: {this.EmpName}";
}
}
I am designing a winform in which I have a datagridview with predefined columns, the first column is a combobox and rest 3 columns are textboxes.
I am not binding datagridview to any datasource since the user is going to fill the last column "Qty", all I want to achieve is, when user clicks on the combobox it should show 3 columns from the database table (item code, item name and uom) and when user select any particular "item code" corresponding "item name" and "uom" should be displayed in second column and third column of the datagridview. Likewise the user should be able to enter as many row as he require. After data entry the data will be saved in a table named "purchase requisition".
I have not done any coding so far and have designed only the form.
See if the following will provide base code to roll with. There are several classes to mock up data and a extension method which should be move to own files.
DataGridView was not configured in the designer, just in code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace UnboundDataGridViewComboBox
{
public partial class Form1 : Form
{
private ComboBox _cbo;
private string _comboColumnName = "ItemCodeColumn";
private List<Item> _items => Mocked.Items;
public Form1()
{
InitializeComponent();
Shown += OnShown;
}
private void OnShown(object sender, EventArgs e)
{
var column1 = new DataGridViewComboBoxColumn
{
DataSource = _items.Select(x => x.ItemCode).ToArray(),
DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing,
Name = _comboColumnName,
HeaderText = "Item Code",
SortMode = DataGridViewColumnSortMode.NotSortable
};
var column2 = new DataGridViewTextBoxColumn
{
Name = "ItemNameColumn",
HeaderText = "Item Name"
};
var column3 = new DataGridViewTextBoxColumn
{
Name = "UomColumn",
HeaderText = "UOM"
};
var column4 = new DataGridViewTextBoxColumn
{
Name = "QuanityColumn",
HeaderText = "Quanity"
};
ItemsDataGridView.Columns.AddRange(column1, column2, column3, column4);
ItemsDataGridView.EditingControlShowing += DataGridView1OnEditingControlShowing;
}
private void DataGridView1OnEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (!ItemsDataGridView.CurrentCell.IsComboBoxCell()) return;
if (ItemsDataGridView.Columns[ItemsDataGridView.CurrentCell.ColumnIndex].Name != _comboColumnName) return;
_cbo = e.Control as ComboBox;
_cbo.SelectedIndexChanged -= ItemCodeColumnComboSelectionChanged;
_cbo.SelectedIndexChanged += ItemCodeColumnComboSelectionChanged;
}
private void ItemCodeColumnComboSelectionChanged(object sender, EventArgs e)
{
DataGridViewComboBoxEditingControl control = sender as DataGridViewComboBoxEditingControl;
Item item = _items.FirstOrDefault(x => x.ItemCode == control.EditingControlFormattedValue.ToString());
if (item == null)
{
return;
}
ItemsDataGridView.CurrentRow.Cells[1].Value = item.Name;
ItemsDataGridView.CurrentRow.Cells[2].Value = item.UOM;
}
}
#region Place classes into their own files
public static class Extensions
{
public static bool IsComboBoxCell(this DataGridViewCell sender)
=> sender.EditType != null &&
sender.EditType == typeof(DataGridViewComboBoxEditingControl);
}
// represents a table in a database
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string ItemCode { get; set; }
public string UOM { get; set; }
public override string ToString() => ItemCode;
}
class Mocked
{
// simulate data from database
public static List<Item> Items => new List<Item>()
{
new Item() {Id = 1,Name = "P1", ItemCode = "A100", UOM = "Q1"},
new Item() {Id = 2,Name = "P2", ItemCode = "A200", UOM = "W1"},
new Item() {Id = 3,Name = "P3", ItemCode = "A300", UOM = "B1"},
new Item() {Id = 4,Name = "P4", ItemCode = "A400", UOM = "H1"}
};
}
#endregion
}
I have a business object that returns a list of objects. This list is then being used as a datasource for a datagridview on a winform. I load my list, set it to the datasource, refresh and view. One of the columns is present but has no values. I see the header but no data. The column is for TruckColorId. Id shows the correct value. Debugging the code I can see that there are objects in the list with all the properties I expect to see correctly with data, including the field in question.
If I select a row and do a foreach loop of the selected row all columns have value but the TruckColorId.
public class TruckColor : EditBase
{
public int TruckColorId { get; set; }
public override int Id
{
get { return TruckColorId; }
set { TruckColorId = value; }
}
}
public class EditBase
{
public virtual int Id { get; set; }
public string ShortCode { get; set; }
public string Description { get; set; }
public IList<EditBase> GetAll()
{
return new List<EditBase>()
{
new TruckColor
{
Description = "abc",
Id = 1,
ShortCode = "A"
},
new TruckColor
{
Description = "abcd",
Id = 2,
ShortCode = "B"
},
new TruckColor
{
Description = "abcde",
Id = 3,
ShortCode = "C"
},
};
}
}
And here is the code in my form to load the trucks:
public void InitTrucks()
{
TruckColor truck = new TruckColor();
var trucks = truck.GetAll();
if (trucks.Count() > 0)
{
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = trucks;
dataGridView1.Refresh();
}
}
try this
var trucks = truck.GetAll();
if (trucks.Count() > 0)
{
List<TruckColor> RealTrucks = trucks.Select(x=>(TruckColor)x).ToList();
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = RealTrucks;
dataGridView1.Refresh();
}
private void Submit_Click(object sender, EventArgs e)
{
ScoutContext db = new ScoutContext();
ScoutData cust = new ScoutData();
cust.FName = textBox1.Text;
cust.LName = textBox2.Text;
cust.FName = textBox3.Text;
cust.FaWork = textBox4.Text;
cust.MoName = textBox5.Text;
cust.MaWork = textBox6.Text;
cust.PlaceOfBirth = textBox7.Text;
cust.City = textBox8.Text;
cust.School = textBox9.Text;
cust.FaceBook = textBox10.Text;
cust.Phone = textBox11.Text;
cust.MPhone = textBox12.Text;
cust.IDNumber = textBox13.Text;
cust.NOfQaid = textBox14.Text;
cust.GroupID = ?????????????????
db.SaveChanges();
}
i work on Windows form, i have this data that the user fill the textbox, after that i need to save the data to my context ( database ), this is my code to insert data to my data base , but i have data ( numbers and some string ) the user will chose from ComboBox. i need to get this data and save it to a list of object , this is the code :
public class Groups
{
[Key]
public string GroupsID { set; get; }
public string NameOfGroup { set; get; }
***public virtual List<ScoutData> Members { set; get; }***
}
The context:
public class ScoutContext : DbContext
{
public ScoutContext()
: base("Scout")
{
// if (!Database.Exists("ScoutData"))
// Database.SetInitializer(new DropCreateDatabaseAlways<ScoutContext>());
}
public DbSet<ScoutData> ScoutDatas { set; get; }
public DbSet<Groups> GroupesScout { set; get; }
}
i need to get this data from the combobox to Members list and save it to a list of object (Members)
It depends on what you have in the combobox.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var combo = sender as ComboBox;
// If combobox has ScoutData then do this
var item = combo.SelectedItem as ScoutData;
// If combobox has something else then do this
var item2 = combo.SelectedItem as SomeThingElse;
var newScout = new ScoutData { FName = item2.FName /*, etc, etc */ };
// Then add it to your list
}
Like the title says, I would like to be able to add buttons in a DataGridView from a List.
What I have so far:
public class Users
{
public Int64 UserID { get; set; }
public DataGridViewButtonColumn EmailAddress { get; set; }
public DataGridViewButtonColumn Gamertag { get; set; }
public DataGridViewButtonColumn Xuid { get; set; }
public String SignedIn { get; set; }
public String AutoSignin { get; set; }
public Image Gamerpic { get; set; }
}
private List<Users> GetUsersList()
{
try
{
List<Users> list = new List<Users>();
IEnumerable<XboxUser> users = _xbc.Users;
foreach (XboxUser user in users)
{
DataGridViewButtonColumn EmailAddress = new DataGridViewButtonColumn()
{
Text = user.EmailAddress
};
DataGridViewButtonColumn Gamertag = new DataGridViewButtonColumn()
{
Text = user.GamerTag
};
DataGridViewButtonColumn Xuid = new DataGridViewButtonColumn()
{
Text = user.Xuid
};
Users xbuser = new Users()
{
UserID = user.UserId,
EmailAddress = EmailAddress,
Gamertag = Gamertag,
Xuid = Xuid,
SignedIn = user.IsSignedIn.ToString(),
AutoSignin = user.AutoSignIn.ToString(),
Gamerpic = GetImageFromUrl(Gamertag.Text)
};
list.Add(xbuser);
}
return list;
}
catch (Exception ex)
{
}
return null;
}
private void Bo_Refresh_Click(object sender, EventArgs e)
{
List<Users> listUsers = GetUsersList();
Dg_UserList.DataSource = new BindingSource(new BindingList<Users>(listUsers), null);
}
private void Dg_UserList_CellClick(object sender, DataGridViewCellEventArgs e)
{
switch (e.ColumnIndex)
{
case 1:
Clipboard.SetText(Dg_UserList.Rows[e.RowIndex].Cells["EmailAddress"].Value.ToString());
MessageBox.Show("Email " + Dg_UserList.Rows[e.RowIndex].Cells["EmailAddress"].Value.ToString() + " has been copied in the clipboard.", "Copy to Clipboard", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case 2:
Clipboard.SetText(Dg_UserList.Rows[e.RowIndex].Cells["Gamertag"].Value.ToString());
MessageBox.Show("Gamertag " + Dg_UserList.Rows[e.RowIndex].Cells["Gamertag"].Value.ToString() + " has been copied in the clipboard.", "Copy to Clipboard", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case 3:
Clipboard.SetText(Dg_UserList.Rows[e.RowIndex].Cells["Xuid"].Value.ToString());
MessageBox.Show("Xuid " + Dg_UserList.Rows[e.RowIndex].Cells["Xuid"].Value.ToString() + " has been copied in the clipboard.", "Copy to Clipboard", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
}
}
Everything appears correctly (even the Image in Gamerpic) except the buttons, which show DataGridViewButtonColumn { Name=, Index=-1 } instead of a button with the right value on it.
I tried with DataGridVewButtonCell as well but does not work either.
However, when I click on a cell that is supposed to be a button, the Clipboard.SetText works but always put DataGridViewButtonColumn { Name=, Index=-1 } in it.
EDIT:
I have been able to do it with Strings instead... Looks less user friendly since there is no button to tell that you can click on it... but it works! FOr sure I would prefer buttons instead :)
Problem
When DataSourced, the DataGridView will auto-create columns based on the data type for each column. By default, each column here is created as a DataGridViewTextBoxColumn, except for the column bound to an Image - which will default to a DataGridViewImageColumn. Even though you have three DataGridViewButtonColumn properties, they will be bound to text columns - which will set the value as follows (example):
NewRow.Cells[1].Value = DataSourceObject.EmailAddress.ToString();
// I.E. EmailAddress is a DataGridViewButtonColumn, so...
NewRow.Cells[1].Value = DataGridViewButtonColumn.ToString();
Console.WriteLine(DataGridViewButtonColumn.ToString()); // prints "DataGridViewButtonColumn { Name=, Index=-1 }"
Solution
Start with the Users class: Change all the DatagridViewButtonColumn properties to type string.
public class Users
{
public Int64 UserID { get; set; }
public String EmailAddress { get; set; }
public String Gamertag { get; set; }
public String Xuid { get; set; }
public String SignedIn { get; set; }
public String AutoSignin { get; set; }
public Image Gamerpic { get; set; }
}
And change your GetUserList method to account for the differences:
private List<Users> GetUsersList()
{
try
{
List<Users> list = new List<Users>();
IEnumerable<XboxUser> users = _xbc.Users;
foreach (XboxUser user in users)
{
Users xbuser = new Users()
{
UserID = user.UserId,
EmailAddress = user.EmailAddress,
Gamertag = user.Gamertag,
Xuid = user.Xuid,
SignedIn = user.IsSignedIn.ToString(),
AutoSignin = user.AutoSignIn.ToString(),
Gamerpic = GetImageFromUrl(Gamertag.Text)
};
list.Add(xbuser);
}
return list;
}
catch (Exception ex)
{
}
return null;
}
And finally, in your Form constructor or Load event - before you've bound your data - manually add the columns like so:
Dg_UserList.AutoGenerateColumns = false;
DataGridViewTextBoxColumn userCol = new DataGridViewTextBoxColumn();
DataGridViewButtonColumn emailCol = new DataGridViewButtonColumn();
DataGridViewButtonColumn tagCol = new DataGridViewButtonColumn();
DataGridViewButtonColumn xuidCol = new DataGridViewButtonColumn();
DataGridViewTextBoxColumn signCol = new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn autoCol = new DataGridViewTextBoxColumn();
DataGridViewImageColumn picCol = new DataGridViewImageColumn();
userCol.Name = "UserID"; // Allows access to columns or
emailCol.Name = "EmailAddress"; // cells in the following manner:
tagCol.Name = "Gamertag"; // dgv.Rows[index].Cells["Name"];
xuidCol.Name = "Xuid";
signCol.Name = "SignedIn";
autoCol.Name = "AutoSignin";
picCol.Name = "Gamerpic";
userCol.DataPropertyName = "UserID"; // MUST match DataSource properties.
emailCol.DataPropertyName = "EmailAddress"; // Allows DataSourced columns to match
tagCol.DataPropertyName = "Gamertag"; // up with manually created columns.
xuidCol.DataPropertyName = "Xuid";
signCol.DataPropertyName = "SignedIn";
autoCol.DataPropertyName = "AutoSignin";
picCol.DataPropertyName = "Gamerpic";
userCol.HeaderText = "User ID"; // Allows displaying different text
emailCol.HeaderText = "Email Address"; // for the column headers.
tagCol.HeaderText = "Gamer Tag";
xuidCol.HeaderText = "Xuid";
signCol.HeaderText = "Signed In";
autoCol.HeaderText = "Auto Sign in";
picCol.HeaderText = "Avatar";
Dg_UserList.Columns.Add(userCol);
Dg_UserList.Columns.Add(emailCol);
Dg_UserList.Columns.Add(tagCol);
Dg_UserList.Columns.Add(xuidCol);
Dg_UserList.Columns.Add(signCol);
Dg_UserList.Columns.Add(autoCol);
Dg_UserList.Columns.Add(picCol);
This will allow you to create your button columns but will still allow you to bind the data instead of manually adding each row. Thanks to DataPropertyName the button cells will correctly display the bound cell value.