I am trying to format my cells inside wpf DataGrid control but i am having problems with it.
I am having class like this:
class WashItem
{
private DateTime _Time = DateTime.Now;
private string _Staff = "Undefined";
private double _Price = 850;
public string Staff { get => _Staff; set => _Staff = value; }
public DateTime Time { get => _Time; set => _Time = value; }
public double Price { get => _Price; set => _Price = value; }
}
and I am populating my datagrid like this
private void ReloadData()
{
string[] lines = File.ReadAllLines("baza.txt");
double ukupnaVrednost = 0;
DataTable table = new DataTable();
DataColumn col1 = new DataColumn("Osoblje");
DataColumn col2 = new DataColumn("Vreme");
DataColumn col3 = new DataColumn("Cena");
table.Columns.Add(col1);
table.Columns.Add(col3);
table.Columns.Add(col2);
for (int i = 0; i < lines.Length; i++)
{
WashItem item = JsonConvert.DeserializeObject<WashItem>(lines[i]);
DataRow row = table.NewRow();
row["Osoblje"] = item.Staff;
row["Vreme"] = item.Time;
row["Cena"] = item.Price;
table.Rows.Add(row);
ukupnaVrednost += item.Price;
}
dataGridView.ItemsSource = table.AsDataView();
UkupnoOprano.Content = "Ukupno oprano vozila: " + lines.Length;
UkupnoOpranoVrednost.Content = "Vrednost: " + ukupnaVrednost.ToString("#,##0.00");
}
then I have created datagrid like this
<DataGrid Name="dataGridView" AutoGenerateColumns="true" AutoGeneratingColumn="dataGridView_AutoGeneratingColumn"></DataGrid>
and finally here is my dataGridView_AutoGeneratingColumn function
private void dataGridView_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if(e.PropertyName == "Cena")
{
((DataGridTextColumn)e.Column).Binding.StringFormat = "#,##0.00 rsd";
}
else if(e.PropertyName == "Vreme")
{
((DataGridTextColumn)e.Column).Binding.StringFormat = "dd/MM/yyyy";
}
}
Auto generate columns function get's fired and it does enter if block but at the end my data is still the same - not formatted.
I would say you need to set DataType for DataColumns, because required formats are specific to those types, and won't work for object type.
DataTable table = new DataTable
{
Columns =
{
new DataColumn("Osoblje"),
new DataColumn("Vreme", typeof(DateTime)),
new DataColumn("Cena", typeof(double))
}
};
Related
I have two columns in Datagridview, one for the price excluding Vat and another one for price including Vat, I want it to be dynamic, if I alter the price excluding vat it updates the column including Vat, and if I Update the including Vat column it updates the excluding VAT column vice-versa.
I would appreciate if anyone can help me with the right code for it in C#.
Here´s the code I´m using the calculation to one direction I need the code for the inverse.
private void dgv_Filho_CellEndEdit_1(object sender, DataGridViewCellEventArgs e)
{
bool Check = Convert.ToBoolean(dgv_Filho.CurrentRow.Cells["Check_Filho"].Value);
string Medida_1 = Convert.ToString(dgv_Filho.CurrentRow.Cells["Medida_1"].Value);
string Medida_2 = Convert.ToString(dgv_Filho.CurrentRow.Cells["Medida_2"].Value);
var Iva = Convert.ToDecimal(cb_Iva.Text);
if (Check)
{
if (!string.IsNullOrWhiteSpace(tb_CodigoArtigo.Text) || !string.IsNullOrWhiteSpace(tb_Descricao.Text))
{
dgv_Filho.CurrentRow.Cells["ArtigoPai"].Value = tb_CodigoArtigo.Text;
dgv_Filho.CurrentRow.Cells["Descricao_Pai"].Value = tb_Descricao.Text + " " + Medida_1 + Medida_2;
dgv_Filho.CurrentRow.Cells["CodigoArtigoFilho"].Value = tb_CodigoArtigo.Text + Medida_1 + Medida_2;
//dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value = tb_PVP1.Text;
decimal PrecoFilho = Convert.ToDecimal(dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value);
if (PrecoFilho > 0)
{
decimal PrecoFilhoComIva = PrecoFilho * Iva / 100 + PrecoFilho;
dgv_Filho.CurrentRow.Cells["PrecoFilhoComIva"].Value = PrecoFilhoComIva;
}
}
else
{
dgv_Filho.CurrentRow.Cells["ArtigoPai"].Value = string.Empty;
dgv_Filho.CurrentRow.Cells["Descricao_Pai"].Value = string.Empty;
}
}
}
This isn't too difficult using your existing code:
First of all, use the name of the edited column in if/else if statements to filter which conversion should take place, so that changing the VAT column doesn't get overwritten by the preVAT column. Then, use the opposite algebraic expression of the one you already have written to convert the postVAT price back to the preVAT
Here is what it will look like:
dgv_Filho.CurrentRow.Cells["ArtigoPai"].Value = tb_CodigoArtigo.Text;
dgv_Filho.CurrentRow.Cells["Descricao_Pai"].Value = tb_Descricao.Text + " " + Medida_1 + Medida_2;
dgv_Filho.CurrentRow.Cells["CodigoArtigoFilho"].Value = tb_CodigoArtigo.Text + Medida_1 + Medida_2;
decimal PrecoFilho = Convert.ToDecimal(dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value);
decimal PrecoFilhoComIva = Convert.ToDecimal(dgv_Filho.CurrentRow.Cells["PrecoFilhoComIva"].Value);
if (dgv_Filho.Columns[e.ColumnIndex].Name == "PrecoFilhoSemIva")
{
PrecoFilhoComIva = PrecoFilho * (Iva / 100) + PrecoFilho;
dgv_Filho.CurrentRow.Cells["PrecoFilhoComIva"].Value = PrecoFilhoComIva;
}
else if (dgv_Filho.Columns[e.ColumnIndex].Name == "PrecoFilhoComIva")
{
decimal PrecoFilhoSemIva = PrecoFilhoComIva - (PrecoFilhoComIva / (1 + (Iva / 100)) * (Iva / 100));
dgv_Filho.CurrentRow.Cells["PrecoFilhoSemIva"].Value = PrecoFilhoSemIva;
}
Using this code, editing the preVAT value will automatically update the postVAT value accordingly, and editing the postVAT value will automatically update the preVAT value accordingly
Rather than interact with the DataGridView directly (which can be complex) you could instead make a class that implements INotifyPropertyChanged and keeps all of its internal calculations up-to-date at all times (which is easier). Here is a simplified version of such a class that responds to changes of Descricao, Medida and PrecoFilhoSemIva.
Simplified class that represents a row of data
class Articulo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
string _descricao = string.Empty;
public string Descricao
{
get => _descricao;
set
{
if (!Equals(_descricao, value))
{
_descricao = value;
OnPropertyChanged();
}
}
}
public string Descricao_Pai => $"{Descricao} {Medida_1}#{_precoFilhoSemIva.ToString("F2")}";
public decimal PrecoFilhoComIva => _precoFilhoSemIva * (1.0m + MainForm.Iva);
decimal _medida = 0;
public decimal Medida
{
get => _medida;
set
{
if (!Equals(_medida, value))
{
_medida = value;
OnPropertyChanged();
}
}
}
decimal _precoFilhoSemIva = 0;
public decimal PrecoFilhoSemIva
{
get => _precoFilhoSemIva;
set
{
if (!Equals(_precoFilhoSemIva, value))
{
_precoFilhoSemIva = value;
OnPropertyChanged();
}
}
}
string _codigoArtigo = System.Guid.NewGuid().ToString().Substring(0, 10).ToUpper();
public string CodigoArtigo
{
get => _codigoArtigo;
set
{
if (!Equals(_codigoArtigo, value))
{
_codigoArtigo = value;
OnPropertyChanged();
}
}
}
}
Instances of this class are placed in a BindingList which is assigned to the DataSource property of dgv_Filho and caused the DGV to update whenever the Refresh method is called.
Initializations
The only interaction that should be necessary with the DGV is to initialize the columns and bindings properly in the MainForm override for the Load event. This is also where we bind the combo box to a static value for Iva that can be used by the calculation for the row items.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
initDataGridView();
initComboBox();
}
private void initDataGridView()
{
dgv_Filho.DataSource = DataSource;
DataSource.ListChanged += (sender, e) =>
{
if (e.ListChangedType == ListChangedType.ItemChanged)
{
dgv_Filho.Refresh();
}
};
// Add one or more items to autogenerate the columns.
Random randomPriceGen = new Random(1);
for (int i = 1; i <= 3; i++)
{
var preco = i == 1 ? 1.0m : (decimal)randomPriceGen.NextDouble() * 100;
DataSource.Add(new Articulo
{
Descricao = $"Articulo {(char)('A' + (i - 1))}",
Medida = i,
PrecoFilhoSemIva = preco,
});
}
// Do a little column formatting
foreach (DataGridViewColumn column in dgv_Filho.Columns)
{
switch (column.Name)
{
case nameof(Articulo.Descricao):
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
column.MinimumWidth = 120;
break;
case nameof(Articulo.Medida):
case nameof(Articulo.PrecoFilhoSemIva):
case nameof(Articulo.PrecoFilhoComIva):
column.DefaultCellStyle.Format = "F2";
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
break;
default:
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
break;
}
}
}
private void initComboBox()
{
cb_Iva.SelectedIndex = 0;
cb_Iva.SelectedIndexChanged += onIvaSelected;
cb_Iva.KeyDown += (sender, e) =>
{
if( e.KeyData == Keys.Enter)
{
e.Handled = e.SuppressKeyPress = true;
}
onIvaSelected(sender, e);
};
onIvaSelected(cb_Iva, EventArgs.Empty);
void onIvaSelected(object sender, EventArgs e)
{
if (decimal.TryParse(cb_Iva.Text.Replace("%", string.Empty), out decimal iva))
{
Iva = iva / 100m;
dgv_Filho.Refresh();
cb_Iva.BackColor = SystemColors.Window;
}
else cb_Iva.BackColor = Color.LightSalmon;
}
}
I working with C# and EF 6.4 and I am looking for clean and easy solution for my problem.
I have simple base like that:
and I want to load data to DataGridView to be looked like that:
I have tried the following solutions:
1
//sorting working, but doesn`t show columns "name" and "title"
Db.BooksAuthors.Include(x => x.Authors).Load();
DataGridView1.DataSource = Db.BooksAuthors.Local.ToBindingList;
2
//sorting not working, but shows columns "name" and "title"
public class BooksAuthorsView
{
public Int32 idBook { get; set; }
public Int32 idAuthor { get; set; }
public string BookTitle { get; set; }
public string AuthorName { get; set; }
}
private void Show()
{
var list = (from BA in Db.BooksAuthors
select new BooksAuthorsView() { idBook = BA.idBook, idAuthor = BA.idAuthor, BookTitle = BA.Books.title, AuthorName = BA.Authors.name });
DataGridView1.DataSource = new BindingSource() { DataSource = new BindingList<BooksAuthorsView>(list.ToList) };
}
EDIT:
I checked this solution. It`s working, but is it the simplest solution?
If you want to sort by clicking on the column header, you can refer to the following code:
public DataTable dvtodt(DataGridView dv)
{
DataTable dt = new DataTable();
DataColumn dc;
for (int i = 0; i < dv.Columns.Count; i++)
{
dc = new DataColumn();
dc.ColumnName = dv.Columns[i].HeaderText.ToString();
dt.Columns.Add(dc);
}
for (int j = 0; j < dv.Rows.Count; j++)
{
DataRow dr = dt.NewRow();
for (int x = 0; x < dv.Columns.Count; x++)
{
dr[x] = dv.Rows[j].Cells[x].Value;
}
dt.Rows.Add(dr);
}
return dt;
}
private int SortOrder_ = 0;
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
int nColumnIndex = e.ColumnIndex;
DataTable d = dvtodt(dataGridView1);
if (SortOrder_ == 0)
{
d.DefaultView.Sort = this.dataGridView1.Columns[nColumnIndex].Name + " ASC";
SortOrder_ = 1;
}
else if (SortOrder_ == 1)
{
d.DefaultView.Sort = this.dataGridView1.Columns[nColumnIndex].Name + " desc";
SortOrder_ = 0;
}
dataGridView1.Columns.Clear();
dataGridView1.DataSource = d;
}
Image of the application
So there are 4 columns ID,ItemName,ItemCategory and PriceAmount
What i want to do is sort the price amount by clicking the dropdown menu and i took out the price amount added it in an arrray and then sorted it using bubble sort but i am having a hard time finding out how do i update the datagridview as per the price amount and changing its respective columns too any help?
This is what i did
int[] price = new int[dataGridView1.Rows.Count];
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
price[i] = Convert.ToInt32(dataGridView1.Rows[i].Cells[3].Value);
for (int j = 0; j < price.Length; j++)
{
Console.WriteLine(price[j]);
}
}
int temp;
for (int j = 0; j <= price.Length - 2; j++)
{
for (int i = 0; i <= price.Length - 2; i++)
{
if (price[i] > price[i + 1])
{
temp = price[i + 1];
price[i + 1] = price[i];
price[i] = temp;
}
}
}
foreach(int sortedArray in price)
{
Console.Write(sortedArray + " ");
Console.ReadLine();
}
here is the code of the browse button
private void browseBtn_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "Files(*.txt, *.csv)|*.txt;*.csv|All Files (*.*) |*.*";
DialogResult result = dialog.ShowDialog();
if (result == DialogResult.OK)
{
pathTextBox.Text = dialog.FileName;
}
if(pathTextBox.Text.Length>0)
{
importBtn.Enabled = true;
}
}
then it grabs the location of the .csv file and then adds in the textbox
and then the insert button imports it
private void importBtn_Click(object sender, EventArgs e)
{
string value = pathTextBox.Text;
importCSVDataFile(value);
pathTextBox.Text = "";
}
Code of importCSVDataFile
private void importCSVDataFile(string filepath)
{
try
{
TextFieldParser csvreader = new TextFieldParser(filepath);
csvreader.SetDelimiters(new string[] { "," });
csvreader.ReadFields();
//int row_count = 0;
while (!csvreader.EndOfData)
{
string[] fielddata = csvreader.ReadFields();
dataGridView1.Rows.Add();
for (int i = 0; i < fielddata.Length; i++)
{
dataGridView1.Rows[row_count].Cells[i].Value = fielddata[i];
}
row_count++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Import CSV File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I was performing a insert and update work with this
private void insertBtn_Click(object sender, EventArgs e)
{
string id = idTextBox.Text;
string itemName = itemNameTextBox.Text;
string itemCategory = categoryTextBox.Text;
string itemPrice = priceTextBox.Text;
if (this.status)
{
dataGridView1.Rows[this.row].Cells[0].Value = id;
dataGridView1.Rows[this.row].Cells[1].Value = itemName;
dataGridView1.Rows[this.row].Cells[2].Value = itemCategory;
dataGridView1.Rows[this.row].Cells[3].Value = itemPrice;
this.insertBtn.Text = "Save";
dataGridView1.Rows[this.row].Selected = true;
MessageBox.Show("Existing Record Updated");
}
else
{
int count = dataGridView1.Rows.Count;
dataGridView1.Rows[count].Cells[0].Value = id;
dataGridView1.Rows[count].Cells[1].Value = itemName;
dataGridView1.Rows[count].Cells[2].Value = itemCategory;
dataGridView1.Rows[count].Cells[3].Value = itemPrice;
dataGridView1.Rows[count].Selected = true;
MessageBox.Show("New Record Saved!!");
row_count++;
}
itemNameTextBox.Text = "";
categoryTextBox.Text = "";
priceTextBox.Text = "";
this.status = false;
this.row = 0;
}
Sort Algorithm of Bubble Sort for itemName
private void sortByItem()
{
int rows = dataGridView1.Rows.Count;
for (int i = 0; i < rows; i++)
{
for (int j = 1; j < rows; j++)
{
string val1 = Convert.ToString(dataGridView1.Rows[j - 1].Cells[0].Value);
string val2 = Convert.ToString(dataGridView1.Rows[j].Cells[0].Value);
if (string.Compare(val1, val2) > 0)
{
for (int a = 0; a < this.dataGridView1.Columns.Count; a++)
{
object temp = this.dataGridView1[a, j - 1].Value;
this.dataGridView1[a, j - 1].Value = this.dataGridView1[a, j].Value;
this.dataGridView1[a, j].Value = temp;
}
}
}
}
The way you are binding data in the gridview is not right. That way you can not achieve functionality of sorting GridView.
What you need is a class which represents the data which are loading in the gridview.
Let say you have a product class as following.
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public double Price { get; set; }
}
Now you have data of multiple products in the file so you need to create a list of products and initialize it in the form as following.
public partial class Form1 : Form
{
private List<Product> products;
public Form1()
{
products = new List<Product>();
InitializeComponent();
}
}
Now method importCSVDataFile needs to be changed as following to load data from the file and populate the list and bind it to the grid view.
private void importCSVDataFile(string filepath)
{
try
{
TextFieldParser csvreader = new TextFieldParser(filepath);
csvreader.SetDelimiters(new string[] { "," });
csvreader.ReadFields();
while (!csvreader.EndOfData)
{
string[] fielddata = csvreader.ReadFields();
var product = new Product();
product.ID = Convert.ToInt32(fielddata[0]);
product.Name = fielddata[1];
product.Category = fielddata[2];
product.Price = Convert.ToDouble(fielddata[3]);
products.Add(product);
}
dataGridView1.DataSource = products;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Import CSV File", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Once you have data displayed in the grid, you need to change sorting code as following.
Let say you have combobox1 which has column names listed to sort the gridview. So code of combobox1's SelectedIndexChanged event will be as following.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedItem != null)
{
var selectedColumnName = comboBox1.SelectedItem as string;
switch (selectedColumnName)
{
case "ID":
dataGridView1.DataSource = products.OrderBy(product => product.ID).ToList();
break;
case "Name":
dataGridView1.DataSource = products.OrderBy(product => product.Name).ToList();
break;
case "Category":
dataGridView1.DataSource = products.OrderBy(product => product.Category).ToList();
break;
case "Price":
dataGridView1.DataSource = products.OrderBy(product => product.Price).ToList();
break;
}
}
}
To add new products to the gridview you need to create new instance of Product and set its properties and then add it to the list and bind the list to the gridview again.
public void btnInsert_Click(object sender, EventArgs e)
{
var id = Convert.ToInt32(txtId.Text);
var objProduct = products.FirstOrDefault(product => product.ID == id);
if (objProduct == null)
{
objProduct = new Product();
objProduct.ID = id;
objProduct.Name = txtName.Text;
objProduct.Category = txtCategory.Text;
objProduct.Price = Convert.ToDouble(txtPrice.Text);
products.Add(objProduct);
}
else
{
objProduct.Name = txtName.Text;
objProduct.Category = txtCategory.Text;
objProduct.Price = Convert.ToDouble(txtPrice.Text);
}
dataGridView1.DataSource = null;
dataGridView1.DataSource = products;
}
I hope this would help you resolve your issue.
I have a class like this:
public class PricingRecord
{
private string _name;
private float[] _prices;
public PricingRecord(string name, float[] prices)
{
_name = name;
_prices = prices;
}
[DisplayName("Name")]
public string PricingName => _name;
public float[] Prices => _prices;
}
I want to map "Prices" to "Price 1", "Price 2", etc. columns in a DataGridView. I can get the columns to appear, but don't know how to make the mapping work.
Here's the main window:
public partial class MainForm : Form
{
private int _numPricingColumns;
private BindingList<PricingRecord> _records;
public MainForm()
{
InitializeComponent();
SetupPricingData();
SetupGridView();
}
private void SetupPricingData()
{
_records = new BindingList<PricingRecord>();
for (int i = 0; i < 100; i++)
{
var pricing = new PricingRecord($"Name {i + 1}", new [] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f });
_records.Add(pricing);
}
_numPricingColumns = _records[0].Prices.Length;
GridView.DataSource = _records;
}
private void SetupGridView()
{
//GridView.AutoGenerateColumns = false;
//DataGridViewColumn column = new DataGridViewTextBoxColumn
//{
// Name = "Name",
// DataPropertyName = "PricingName"
//};
//GridView.Columns.Add(column);
for (int i = 0; i < _numPricingColumns; i++)
{
DataGridViewColumn column = new DataGridViewTextBoxColumn
{
Name = $"Price {i + 1}",
DataPropertyName = $"Price{i + 1}"
};
GridView.Columns.Add(column);
}
}
}
If I don't use BindingView I can set it up all by hand, but then I have to maintain the rows and columns myself. I'd like to use BindingView but this doesn't seem to support mapping many columns to an array.
I found I could get the pricing columns to be handled by drawing them. The use I needed was readonly so this is my solution for now:
private void OnCellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
for (int i = 0; i < _numPricingColumns; i++)
{
var name = $"Price {i + 1}";
var column = GridView.Columns[name];
if (column.Index == e.ColumnIndex && e.RowIndex >= 0)
{
var row = GridView.Rows[e.RowIndex];
var record = row.DataBoundItem as PricingRecord;
if (record != null)
{
var selected = (e.State & DataGridViewElementStates.Selected) != 0;
using (var brush = new SolidBrush(selected ? e.CellStyle.SelectionForeColor : e.CellStyle.ForeColor))
{
e.PaintBackground(e.ClipBounds, selected);
e.Graphics.DrawString(record.Prices[i].ToString("N"), e.CellStyle.Font, brush,
e.CellBounds.X + 2.0f, e.CellBounds.Y + 2.0f, StringFormat.GenericDefault);
e.Handled = true;
}
}
}
}
}
A faster and more flexible solution proved to be dropping BindingList and directly poking the cells in the grid. The need to map an array field to multiple columns becomes moot as it's done by hand.
I want to have a combobox in a specific cell in my data grid view. can somebody help? For the table I'm using data table
Problem: I want to put a combobox in a specific cell like in column 1 and row 1.
Here is how I populate the table--
public DataTable createGridForForm(int rows, int columns)
{
// Create the output table.
DataTable table = new DataTable();
for (int i = 1; i <= columns; i++)
{
table.Columns.Add("column " + i.ToString());
}
for (int i = 1; i < rows; i++)
{
DataRow dr = table.NewRow();
// populate data row with values here
ListBox test = new ListBox();
myTabPage.Controls.Add(test);
table.Rows.Add(dr);
}
return table;
}
And here is how I create the datagridview.
private void createGridInForm(int rows, int columns)
{
DataGridView RunTimeCreatedDataGridView = new DataGridView();
RunTimeCreatedDataGridView.DataSource = createGridForForm(rows, columns);
//DataGridViewColumn ID_Column = RunTimeCreatedDataGridView.Columns[0];
//ID_Column.Width = 200;
int positionForTable = getLocationForTable();
RunTimeCreatedDataGridView.BackgroundColor = Color.WhiteSmoke;
RunTimeCreatedDataGridView.Size = new Size(995, 200);
RunTimeCreatedDataGridView.Location = new Point(5, positionForTable);
myTabPage.Controls.Add(RunTimeCreatedDataGridView);
}
here is my whole code----
public partial class Form1 : Form
{
String line;
String typeOfTable;
int amountOfTablesInTab;
delegate void SetComboBoxCellType(int iRowIndex);
bool bIsComboBox = false;
List<TabPage> tapPages = new List<TabPage>();
TabPage myTabPage;
DataGridView RunTimeCreatedDataGridView;
private const String TABS = "TABS";
private const String TABLES = "TABLES";
private const String GRID = "grid";
private const String LIST = "list";
private const int LOCATION_TABLE_TYPE = 2;
private const int LOCATION_TABLE_AMOUNT_ROWS = 3;
private const int LOCATION_TABLE_AMOUNT_COLUMNS = 4;
private const int AMOUNT_COLUMNS_IN_LIST = 2;
private const int LOCATION_TAB_FOR_TABLE = 1;
private const int STARTING_POSITION_FOR_TABLES = 5;
private const int TABLE_SIZE= 205;
String[] splitTableArray;
List<String> tabList = new List<String>();
List<String> tablesList = new List<String>();
public Form1()
{
InitializeComponent();
//test();
getFormContentFromFile();
}
private void getFormContentFromFile()
{
using (StreamReader reader = new StreamReader("neo2G.res"))
{
while (!reader.EndOfStream)
{
line = reader.ReadLine();
if (line.Equals(TABS))
{
while (!line.Equals(".."))
{
line = reader.ReadLine();
if (!line.Equals("..") && !line.Equals(""))
{
tabList.Add(line);
}
}
}
if (line.Equals(TABLES))
{
while (!line.Equals(".."))
{
line = reader.ReadLine();
if (!line.Equals(".."))
{
tablesList.Add(line);
}
}
}
}
createTablesInTab();
}
}
private void searchTablesToMatch(int tabCount)
{
int tableCount = 0;
int tabLocationForTables;
amountOfTablesInTab = 0;
foreach(String table in tablesList)
{
splitTableLineToArray(tablesList[tableCount]);
if (int.TryParse(splitTableArray[LOCATION_TAB_FOR_TABLE], out tabLocationForTables))
{
if(tabLocationForTables == tabCount)
{
typeOfTable = splitTableArray[LOCATION_TABLE_TYPE];
amountOfTablesInTab++;
if(typeOfTable.Equals(LIST))
{
createListInForm(int.Parse(splitTableArray[LOCATION_TABLE_AMOUNT_ROWS]));
}
else if(typeOfTable.Equals(GRID))
{
createGridInForm(int.Parse(splitTableArray[LOCATION_TABLE_AMOUNT_ROWS]), int.Parse(splitTableArray[LOCATION_TABLE_AMOUNT_COLUMNS]));
}
}
{
}
}
else
{
MessageBox.Show("The format for TABLES must be identical to the table format in the Configuration file format", "File Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
tableCount++;
}
}
private int getLocationForTable()
{
int position = 0;
for (int i = 1; i <= amountOfTablesInTab; i++)
{
position = position + TABLE_SIZE;
if (i == 1)
{
position = STARTING_POSITION_FOR_TABLES;
}
}
return position;
}
private void createGridInForm(int rows, int columns)
{
RunTimeCreatedDataGridView = new DataGridView();
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
myTabPage.Controls.Add(RunTimeCreatedDataGridView);
c.Items.Add("A");
c.Items.Add("B");
c.Items.Add("C");
RunTimeCreatedDataGridView.DataSource = createGridForForm(rows, columns);
//Assign it to your dataGridView
RunTimeCreatedDataGridView.Rows[1].Cells[1] = c;
int positionForTable = getLocationForTable();
RunTimeCreatedDataGridView.BackgroundColor = Color.WhiteSmoke;
RunTimeCreatedDataGridView.Size = new Size(995, 200);
RunTimeCreatedDataGridView.Location = new Point(5, positionForTable);
}
private void createListInForm(int rows)
{
RunTimeCreatedDataGridView = new DataGridView();
RunTimeCreatedDataGridView.DataSource = createListForForm(rows);
int positionForTable = getLocationForTable();
RunTimeCreatedDataGridView.BackgroundColor = Color.WhiteSmoke;
RunTimeCreatedDataGridView.Size = new Size(995, 200);
RunTimeCreatedDataGridView.Location = new Point(5, positionForTable);
myTabPage.Controls.Add(RunTimeCreatedDataGridView);
}
private void createTablesInTab()
{
int countTab = 0;
foreach (String tab in tabList)
{
countTab++;
createTabInForm(tab);
searchTablesToMatch(countTab);
}
}
private void createTabInForm(String tabName)
{
tabName = Regex.Replace(tabName, #"[\d-]", string.Empty);
tabName = tabName.Trim(':', '"');
myTabPage = new TabPage(tabName);
tabControl1.TabPages.Add(myTabPage);
myTabPage.AutoScroll = true;
}
private void splitTableLineToArray(String tableLine)
{
splitTableArray = tableLine.Split(',');
}
public DataTable createGridForForm(int rows, int columns)
{
// Create the output table.
DataTable table = new DataTable();
for (int i = 1; i <= columns; i++)
{
table.Columns.Add("column " + i.ToString());
}
for (int i = 1; i < rows; i++)
{
DataRow dr = table.NewRow();
// populate data row with values here
table.Rows.Add(dr);
}
return table;
}
public DataTable createListForForm(int rows)
{
// Create the output table.
DataTable table = new DataTable();
for (int i = 1; i <= AMOUNT_COLUMNS_IN_LIST ; i++)
{
table.Columns.Add("column " + i.ToString());
}
for (int i = 1; i < rows; i++)
{
DataRow dr = table.NewRow();
// populate data row with values here
table.Rows.Add(dr);
}
return table;
}
}
You have to create the 'combo box' first by using DataGridViewComboBoxCell class
this class has quite similar properties to the original comboBox
Try this
//Create comboBox
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
c.Items.Add("A");
c.Items.Add("B");
c.Items.Add("C");
//Assign it to your dataGridView
yourDataGridView.Rows[rowNum].Cells[colNum] = c;
You can add RowDatabound event listener to your gridview and in the event you can control the logic you want to implement on.
You can add event listener like below
RunTimeCreatedDataGridView.RowDataBound += new GridViewRowEventHandler(RunTimeCreatedDataGridView_RowDataBound);
the event handler will be
protected void RunTimeCreatedDataGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
// logic to display check box
}
I found the answer
//create columns as textbox columns(or whatever you want)
DataGridViewTextBoxColumn dgc = new DataGridViewTextBoxColumn();
DataGridViewTextBoxColumn dgc1 = new DataGridViewTextBoxColumn();
//add the colums to the table
dataGridView1.Columns.Add(dgc);
dataGridView1.Columns.Add(dgc1);
//set header text here if you wish
//create dgv combobox cells and add items to the collection
DataGridViewComboBoxCell cbc = new DataGridViewComboBoxCell();
cbc.Items.Add("item 1");
cbc.Items.Add("item 2");
DataGridViewComboBoxCell cbc1 = new DataGridViewComboBoxCell();
cbc1.Items.Add("item 1");
cbc1.Items.Add("item 2");
//create 2 rows here so that you can insert future columns without having them go above your comboboxes
dataGridView1.Rows.Add(2);
//set row one cells to combobox cells
dataGridView1.Rows[0].Cells[0] = cbc;
dataGridView1.Rows[0].Cells[1] = cbc1;