Like and Sorting Operation in Grid view - c#

I want sort grid view data using like operator as like SQL Query
SELECT Acc_Name, Opening_bal
FROM Acc_Sub_SubHead
WHERE (Acc_Name LIKE N'%sa%')
ORDER BY CHARINDEX('s', Acc_Name)
i have tried this way
DataTable table = this.GVProductList.DataSource as DataTable;
table.DefaultView.RowFilter = "Name LIKE '%" + txtSearch.Text + "%' ";

I have 2 solutions for you 1 one is using DataTable.
void loadGrid()
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] {
new DataColumn("Acc_Name", typeof(string)),
new DataColumn("Opening_bal",typeof(decimal)) });
dt.Rows.Add("Alpasce", "20");
dt.Rows.Add("Cvcpas", "1000");
dt.Rows.Add("Jpasmal", "500");
dataGridView1.DataSource = dt;
}
void searchAndOrderGrid()
{
DataTable table = this.dataGridView1.DataSource as DataTable;
var results = (from myRow in table.AsEnumerable()
where myRow.Field<string>("Acc_Name").Contains("as")
orderby myRow.Field<string>("Acc_Name").IndexOf("s")
select myRow).ToList();
DataTable dtNew = new DataTable();
dtNew.Columns.AddRange(new DataColumn[2] {
new DataColumn("Acc_Name", typeof(string)),
new DataColumn("Opening_bal",typeof(decimal)) });
if (results != null)
{
foreach (var row in results)
{
dtNew.Rows.Add(row.Field<string>("Acc_Name"), row.Field<decimal>("Opening_bal"));
}
dataGridView1.DataSource = dtNew;
}
}
Note: This is not optimized. You can optimize it or you can do it more efficient way.
2nd Solution is using Class Object
public class Acc_Sub_SubHead
{
public string Acc_Name { get; set; }
public decimal Opening_bal { get; set; }
}
void loadData()
{
List<Acc_Sub_SubHead> Items = new List<Acc_Sub_SubHead>();
Items.Add(new Acc_Sub_SubHead() { Acc_Name = "Alpasce", Opening_bal = 202 });
Items.Add(new Acc_Sub_SubHead() { Acc_Name = "Cvcpas", Opening_bal = 365 });
Items.Add(new Acc_Sub_SubHead() { Acc_Name = "Jpasmal", Opening_bal = 125 });
this.dataGridView1.DataSource = Items;
}
void searchAndOrderby()
{
List<Acc_Sub_SubHead> tempItems = this.dataGridView1.DataSource as List<Acc_Sub_SubHead>;
var orderedData = tempItems.Where(c => c.Acc_Name.Contains("as")).OrderBy(x => x.Acc_Name.IndexOf("s")).ToList();
this.dataGridView1.DataSource = orderedData;
}
Note: I like the second way. It is more efficient and faster than the first one. I have tested both codes and it works. Please check and let me know.

Related

Unable to add Rows to DataGridView programically

I'm have created a purchase order form and added all data to tables. now I wanted to update purchase order items by adding new items to DataGridView.
I have filled DataGridView with old items and now I wanted to add new items but it is not working
Error: Rows cannot be programmatically added to the DataGridView rows collection when the control is data-bound.
Here is my code which I'm using to add a new row in updateMode.
try
{
if (updateMode)
{
//DataTable dt = dataGridPOItems.DataSource as DataTable;
//DataRow rw = dt.NewRow();
//DataTable dt = dataGridPOItems.DataSource as DataTable;
//DataRow rw = dt.NewRow();
//var dataSource = dataGridPOItems.DataSource as BindingSource;
//var dataTable = dataSource.DataSource as DataTable;
DataTable dt = dataGridPOItems.DataSource as DataTable;
dt.Rows.Add();
dataGridPOItems.DataSource = dt;
int rowIndex = this.dataGridPOItems.RowCount;
var row = this.dataGridPOItems.Rows[rowIndex];
row.Cells["Product_ID"].Value = txtPOProdID.Text;
row.Cells["HSN"].Value = txtPOProdHSN.Text;
row.Cells["EAN"].Value = txtPOProdBarcode.Text;
row.Cells["PName"].Value = txtPOProdName.Text;
row.Cells["OrderQty"].Value = txtPOProdQtyReq.Text;
row.Cells["PMargin"].Value = txtPOProdMargin.Text;
row.Cells["MRP"].Value = txtPOProdMRP.Text;
row.Cells["GSTRate"].Value = txtPOProdGST.Text;
row.Cells["LandingCost"].Value = Math.Round(Convert.ToDecimal(row.Cells["MRP"].Value) - ((Convert.ToDecimal(row.Cells["MRP"].Value) * Convert.ToDecimal(row.Cells["PMargin"].Value) / 100)), 2);
row.Cells["BCost"].Value = Math.Round(Convert.ToDecimal(row.Cells["LandingCost"].Value) / (Convert.ToDecimal(row.Cells["GSTRate"].Value) / 100 + 1), 2);
row.Cells["BCostAmt"].Value = Convert.ToDecimal(row.Cells["BCost"].Value) * Convert.ToDecimal(row.Cells["OrderQty"].Value);
row.Cells["GSTAmt"].Value = Math.Round((Convert.ToDecimal(row.Cells["BCostAmt"].Value) * (Convert.ToDecimal(row.Cells["GSTRate"].Value) / 100)), 2);
row.Cells["NetAmt"].Value = Convert.ToDecimal(row.Cells["BCostAmt"].Value) + Convert.ToDecimal(row.Cells["GSTAmt"].Value);
txtPOProdQtyReq.Clear();
txtPOTotalItems.Text = Convert.ToString(rowIndex + 1);
foreach (DataGridViewColumn column in dataGridPOItems.Columns)
{
txtPOTotalQty.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[4].Value)).ToString();
txtPOTCost.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[12].Value)).ToString();
txtPOTAX.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[10].Value)).ToString();
}
ClassControlsHandler.ClearAll(this.groupProdInfo);
txtPOProdID.Focus();
}
else
{
int rowIndex = this.dataGridPOItems.Rows.Add();
var row = this.dataGridPOItems.Rows[rowIndex];
row.Cells["ProductID"].Value = txtPOProdID.Text;
row.Cells["HSN"].Value = txtPOProdHSN.Text;
row.Cells["EAN"].Value = txtPOProdBarcode.Text;
row.Cells["PName"].Value = txtPOProdName.Text;
row.Cells["OrderQty"].Value = txtPOProdQtyReq.Text;
row.Cells["PMargin"].Value = txtPOProdMargin.Text;
row.Cells["MRP"].Value = txtPOProdMRP.Text;
row.Cells["GSTRate"].Value = txtPOProdGST.Text;
row.Cells["LandingCost"].Value = Math.Round(Convert.ToDecimal(row.Cells["MRP"].Value) - ((Convert.ToDecimal(row.Cells["MRP"].Value) * Convert.ToDecimal(row.Cells["PMargin"].Value) / 100)), 2);
row.Cells["BCost"].Value = Math.Round(Convert.ToDecimal(row.Cells["LandingCost"].Value) / (Convert.ToDecimal(row.Cells["GSTRate"].Value) / 100 + 1), 2);
row.Cells["BCostAmt"].Value = Convert.ToDecimal(row.Cells["BCost"].Value) * Convert.ToDecimal(row.Cells["OrderQty"].Value);
row.Cells["GSTAmt"].Value = Math.Round((Convert.ToDecimal(row.Cells["BCostAmt"].Value) * (Convert.ToDecimal(row.Cells["GSTRate"].Value) / 100)), 2);
row.Cells["NetAmt"].Value = Convert.ToDecimal(row.Cells["BCostAmt"].Value) + Convert.ToDecimal(row.Cells["GSTAmt"].Value);
txtPOProdQtyReq.Clear();
txtPOTotalItems.Text = Convert.ToString(rowIndex + 1);
foreach (DataGridViewColumn column in dataGridPOItems.Columns)
{
txtPOTotalQty.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[4].Value)).ToString();
txtPOTCost.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[12].Value)).ToString();
txtPOTAX.Text = dataGridPOItems.Rows.OfType<DataGridViewRow>().Sum(r => Convert.ToDecimal(r.Cells[10].Value)).ToString();
}
ClassControlsHandler.ClearAll(this.groupProdInfo);
txtPOProdID.Focus();
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
Expected Results: i just want to add new rows in updateMode.
Thank You.
Can you try it like this?
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.ColumnCount = 3;
dataGridView1.Columns[0].Name = "Product ID";
dataGridView1.Columns[1].Name = "Product Name";
dataGridView1.Columns[2].Name = "Product Price";
string[] row = new string[] { "1", "Product 1", "1000" };
dataGridView1.Rows.Add(row);
row = new string[] { "2", "Product 2", "2000" };
dataGridView1.Rows.Add(row);
row = new string[] { "3", "Product 3", "3000" };
dataGridView1.Rows.Add(row);
row = new string[] { "4", "Product 4", "4000" };
dataGridView1.Rows.Add(row);
}
}
}
http://csharp.net-informations.com/datagridview/csharp-datagridview-add-column.htm
Or, simply.
private void InsertNewRowToDGV()
{
//we have to get the index of a last row id:
int index = this.dataGridView1.Rows.Count;
//and count +1 to get a new row id:
index++;
this.dataGridView1.Rows.Add();
}
It's pretty simple: instead of directly using a DataTable as the DataGridView.DataSource, you can use a BindingSource and set the DataTable as the BindingSource.DataSource.
The BindingSource will then become the DataGridView.DataSource.
private BindingSource dgvBindingSource = null;
Create a DataTable with the required Columns or fill it using a DataAdapter, then:
DataTable dt = new DataTable("TableName");
//Set the Columns or fill it with a DataAdapter
dgvBindingSource = new BindingSource();
dgvBindingSource.DataSource = dt;
dataGridView1.DataSource = dgvBindingSource;
dt.Dispose();
When you need to add a new DataRow to the BindingSource, you can use the BindingSource.DataSource directly - the Fields must be provided in the correct order:
(dgvBindingSource.DataSource as DataTable).Rows.Add(new object[] {
[Field1 Value], [Field2 Value], [Field3 Value], [Field N Value]
});
or add a new DataRow and assign the Fields values using the Columns names:
using (DataTable dt = (dgvBindingSource.DataSource as DataTable))
{
DataRow row = dt.NewRow();
row["Column0"] = SomeValue1;
row["Column1"] = SomeValue2;
row["Column2"] = SomeValue3;
dt.Rows.Add(row);
}
Both methods will updated the DataGridView immediately.

Adding multiple row from one datagridview to datagridview c# windows form

i have this piece of code through which i am inserting one grid view data to another
private void btnADD_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add("LOB");
dt.Columns.Add("Quantity");
dt.Columns.Add("Name");
dt.Columns.Add("Packing");
dt.Columns.Add("Price");
dt.Columns.Add("Code");
dr = dt.NewRow();
dr["LOB"] = txtLOB.Text;
dr["Quantity"] = txtQuantity.Text;
dr["Name"] = txtName.Text;
dr["Packing"] = txtPacking.Text;
dr["Price"] = txtPrice.Text;
dr["Code"] = txtBachNo.Text;
dt.Rows.Add(dr);
gridviewDtaInserted.DataSource = dt;
}
i am able to insert one row at a time but i want to insert many rows one after another.
You should declare DataTable as globally because every time on Button click it has instantiated with new key word.
Try this:
DataTable dt = new DataTable();
dt.Columns.Add("LOB");
dt.Columns.Add("Quantity");
dt.Columns.Add("Name");
dt.Columns.Add("Packing");
dt.Columns.Add("Price");
dt.Columns.Add("Code");
private void btnADD_Click(object sender, EventArgs e)
{
DataRow dr;
for(int i = 0; i <= RowsCountThatYouWantToIsert; i++)
{
dr = dt.NewRow();
dr["LOB"] = txtLOB.Text;
dr["Quantity"] = txtQuantity.Text;
dr["Name"] = txtName.Text;
dr["Packing"] = txtPacking.Text;
dr["Price"] = txtPrice.Text;
dr["Code"] = txtBachNo.Text;
dt.Rows.Add(dr);
}
gridviewDtaInserted.DataSource = dt;
}
IF you are reading from one view to another you can use a looping structure to go through each iteration. I would suggest a for loop so that you can use the current numerical iteration as part of the instruction. if you want to ammend the first view to the second then you may want to use
DataTable dt = new DataTable();
DataTable dt2 = new DataTable();
dt=(DataTable)DataGridViewer1.datasource;
dt2=(DataTable)DataGridViewer2.datasource;
dt2.Merge(dt);
DataGridViewer2.datasource=dt2;
The DataSource property, from a DataGridView accepts a collection of objects.
So, I would suggest you to add how many rows you want to that public collection of objects, and at the end to update the DataSource
gridviewDtaInserted.DataSource = myCollection;
See here more info: MSDN
Also, here is a nice question may help you.
As a skeleton you can design in this way:
public class TestFunctional {
public TestFunctional(){
DataItems = new List<DataItem>();
}
public List<DataItem> DataItems { get; set; }
private void AddOneItem(){
var newItem = new DataItem {
LOB = "a",
Quantity = 1,
Name = "A",
Packing = true,
Code = "a1"
};
DataItems.Add(newItem);
RefreshGrid();
}
private void AddMultipleItems(){
var newItem1 = new DataItem {
LOB = "a",
Quantity = 1,
Name = "A",
Packing = true,
Code = "a1"
};
var newItem2 = new DataItem {
LOB = "b",
Quantity = 2,
Name = "B",
Packing = false,
Code = "b2"
};
DataItems.Add(newItem1);
DataItems.Add(newItem2);
/*or use DataItems.AddRange( ... ) */
RefreshGrid();
}
private void RefreshGrid()
{
gridviewDtaInserted.Rows.Clear();
gridviewDtaInserted.Refresh();
gridviewDtaInserted.DataSource = DataItems;
}
}
public class DataItem{
public string LOB { get; set; }
public double Quantity { get; set; }
public string Name { get; set; }
public bool Packing { get; set; }
public decimal Price { get; set; }
public string Code { get; set; }
}
I hope it will help you. Otherwise, ask :)
Edit:
Also, try to use the BindingList instead of List, I am not sure, but maybe it will automatically update the DataSource of the grid as soon an item is inserted in the collection.
BindingList<DataItem> DataItems

Select 2 or more columns on DataTable using LINQ

I have a DataTable and I want to select multiple columns on the DataTable that matches the input in the textbox. The code below only selects 1 column.
var result = from data in mDataTable.AsEnumerable ()
where data.Field<string>("Code") == txtCode.Text
select data.Field<string> ("Description");
foreach (var res in result) {
txtxDescription.Text = res.ToString ();
}
How can I select 2 or more columns on DataTable using LINQ?
why not select full rows (DataRow object) and then take all necessary values from them?
var rows = mDataTable.AsEnumerable()
.Where(data => data.Field<string>("Code") == txtCode.Text);
foreach(DataRow r in rows)
{
txtxDescription.Text = r.Field<string>("Description");
}
another option is to project data to anonymous objects:
var result = from data in mDataTable.AsEnumerable ()
where data.Field<string>("Code") == txtCode.Text
select new
{
Description = data.Field<string> ("Description"),
Code = data.Field<string> ("Code")
};
foreach (var res in result)
{
// last value always replace `txtxDescription.Text` ??
txtxDescription.Text = res.Description;
txtxCode.Text = res.Code;
}
public void GridviewBinding()
{
DataSet ds = new DataSet();
string constr = ConfigurationManager.ConnectionStrings["SQLMSDB"].ConnectionString;
string sql = "select * from tbl_users";
using (SqlConnection conn = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(sql))
{
cmd.Connection = conn;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(ds);
gridviewcontrol.DataSource = ds;
gridviewcontrol.DataBind();
ViewState["GridViewBindingData"] = ds.Tables[0];
}
}
}
}
protected void btn_searching_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txt_search.Text.Trim().ToString()) || !String.IsNullOrWhiteSpace(txt_search.Text.Trim().ToString()))
{
DataTable dt = (DataTable)ViewState["GridViewBindingData"];
var dataRow = dt.AsEnumerable().Where(x => x.Field<dynamic>("UserName") == txt_search.Text);
DataTable dt2 = dataRow.CopyToDataTable<DataRow>();
gridviewcontrol.DataSource = dt2;
gridviewcontrol.DataBind();
}
else
{
GridviewBinding();
}
}

SqlBulkCopy.WriteToServer doesn't works

Sorry for asking, but I haven't solved my question by reading another situation like I have.
I have an array with longs and I should insert it into a database, that has only 2 fields: OGRN - bigint, data field, Id - int, identity field. I'm creating a DataTable like this
private static DataTable CreateDataTable()
{
var result = new DataTable();
var ogrn = new DataColumn("Ogrn") {DataType = typeof (long), ColumnName = "Ogrn"};
result.Columns.Add(ogrn);
var id = new DataColumn("Id") { DataType = typeof(int), ColumnName = "Id", AutoIncrement = true };
result.Columns.Add(id);
result.PrimaryKey = new[] { id };
return result;
}
after i'm doing this:
var dt = CreateDataTable();
foreach (long ogrn in ogrns)
{
var row = dt.NewRow();
row["Ogrn"] = ogrn;
dt.AcceptChanges();
}
using (var sqlBulkCopy = new SqlBulkCopy(ConnectionString))
{
sqlBulkCopy.DestinationTableName = "dbo.ULs";
sqlBulkCopy.ColumnMappings.Add("Ogrn", "Ogrn");
sqlBulkCopy.ColumnMappings.Add("Id", "Id");
sqlBulkCopy.WriteToServer(dt);
}
So why doesn't it work? Am I missing something important.
Add the new row to the Table!. That is not something that is automagically done when you call NewRow();
var dt = CreateDataTable();
foreach (long ogrn in ogrns)
{
var row = dt.NewRow();
row["Ogrn"] = ogrn.Ogrn;
dt.Rows.Add(row); // ADD the new row to the table!
}
dt.AcceptChanges();

Add an item to combobox before binding data from the database

I had a combobox in a Windows Forms form which retrieves data from a database. I did this well, but I want to add first item <-Please select Category-> before the data from the database. How can I do that? And where can I put it?
public Category()
{
InitializeComponent();
CategoryParent();
}
private void CategoryParent()
{
using (SqlConnection Con = GetConnection())
{
SqlDataAdapter da = new SqlDataAdapter("Select Category.Category, Category.Id from Category", Con);
DataTable dt = new DataTable();
da.Fill(dt);
CBParent.DataSource = dt;
CBParent.DisplayMember = "Category";
CBParent.ValueMember = "Id";
}
}
You could either add the default text to the Text property of the combobox like this (preferred):
CBParent.Text = "<-Please select Category->";
Or, you could add the value to the datatable directly:
da.Fill(dt);
DataRow row = dt.NewRow();
row["Category"] = "<-Please select Category->";
dt.Rows.InsertAt(row, 0);
CBParent.DataSource = dt;
public class ComboboxItem
{
public object ID { get; set; }
public string Name { get; set; }
}
public static List<ComboboxItem> getReligions()
{
try
{
List<ComboboxItem> Ilist = new List<ComboboxItem>();
var query = from c in service.Religions.ToList() select c;
foreach (var q in query)
{
ComboboxItem item = new ComboboxItem();
item.ID = q.Id;
item.Name = q.Name;
Ilist.Add(item);
}
ComboboxItem itemSelect = new ComboboxItem();
itemSelect.ID = "0";
itemSelect.Name = "<Select Religion>";
Ilist.Insert(0, itemSelect);
return Ilist;
}
catch (Exception ex)
{
return null;
}
}
ddlcombobox.datasourec = getReligions();
CBParent.Insert(0,"Please select Category")
You should add "Please select" after you bind data.
var query = from name in context.Version
join service in context.Service
on name.ServiceId equals service.Id
where name.VersionId == Id
select new
{
service.Name
};
ddlService.DataSource = query.ToList();
ddlService.DataTextField = "Name";
ddlService.DataBind();
ddlService.Items.Insert(0, new ListItem("<--Please select-->"));
There are two quick approaches you could try (I don't have a compiler handy to test either one right now):
Add the item to the DataTable before binding the data.
You should be able to simply set CBParent.Text to "<- Please Select Category ->" after you bind the data. It should set the displayed text without messing with the items.
void GetProvince()
{
SqlConnection con = new SqlConnection(dl.cs);
try
{
SqlDataAdapter da = new SqlDataAdapter("SELECT ProvinceID, ProvinceName FROM Province", con);
DataTable dt = new DataTable();
int i = da.Fill(dt);
if (i > 0)
{
DataRow row = dt.NewRow();
row["ProvinceName"] = "<-Selecione a Provincia->";
dt.Rows.InsertAt(row, 0);
cbbProvince.DataSource = dt;
cbbProvince.DisplayMember = "ProvinceName";
cbbProvince.ValueMember = "ProvinceID";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Categories

Resources