Grouping in a sorted asp:GridView - asp.net

I need a grouping in a sorted asp:Gridview like the following picture shows:
Can someone give me a hint about how to proceed? Is it possible to group on RowBound somehow?

You can use the following algorithm to do your work:
/****************************************
* Grouping Algorithmus
* by Björn Karpenstein
* http://www.capri-soft.de/blog
****************************************/
// Nach dieser Spalte soll gruppiert werden
int k = 1;
// Für alle Zeilen (VON UNTEN NACH OBEN)
for (int i = GridView1.Rows.Count - 1; i > 0; i--)
{
GridViewRow row = GridView1.Rows[i];
GridViewRow previousRow = GridView1.Rows[i - 1];
// Für alle Spalten
for (int j = 0; j < row.Cells.Count; j++)
{
if ((row.Cells[k].Text == previousRow.Cells[k].Text) && (row.Cells[j].Text == previousRow.Cells[j].Text))
{
if (previousRow.Cells[j].RowSpan == 0)
{
if (row.Cells[j].RowSpan == 0)
{
previousRow.Cells[j].RowSpan += 2;
}
else
{
previousRow.Cells[j].RowSpan = row.Cells[j].RowSpan + 1;
}
row.Cells[j].Visible = false;
}
}
}
}

You can do this in the RowDataBound event. You have to remember that rowspan and the removal of the next cell has to be done backwards since the next row does not exist yet. row["myValue"] is the column containing the values that need to be compared.
string groupValue = string.Empty;
int rowSpanCount = 1;
//change this to the column index that needs spanning
int columnIndex = 6;
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the current row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//get the current row number
int currentRow = e.Row.DataItemIndex;
//cast the current row to a datarowview
DataRowView row = e.Row.DataItem as DataRowView;
//check if the groupValue equals the current row, if so +1 rowspan in needed
if (groupValue == row["myValue"].ToString())
{
rowSpanCount++;
}
else if (currentRow > 1 && rowSpanCount > 1)
{
//apply rowspan to the first cell
GridView1.Rows[currentRow - rowSpanCount].Cells[columnIndex].RowSpan = rowSpanCount;
//remove the spanned rows
for (int i = 1; i < rowSpanCount; i++)
{
GridView1.Rows[currentRow - (rowSpanCount - i)].Cells.RemoveAt(columnIndex);
}
//reset the rowSpanCount
rowSpanCount = 1;
}
//set the groupValue variable for value comparison in the next row
groupValue = row["myValue"].ToString();
}
}

Related

ASP.Net Rowspan first and second column result to messy gridview design

On Data Bound im trying the below code but result is displaying a different gridview
Final gridview of my code
:
for (int aa = 0; aa < ijp_gridview.Rows.Count; aa++)
{
for (int bb = 2; bb < ijp_gridview.Columns.Count; bb++)
{
if (ijp_gridview.Rows[aa].Cells[bb].Text == "1st Priority" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "2nd Priority" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "3rd Priority" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "No Priority" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "FRESH" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "cutted" ||
ijp_gridview.Rows[aa].Cells[bb].Text == "Backlog")
{
ijp_gridview.Rows[aa].Visible = false;
break;
}
}
}
for (int rowindex = ijp_gridview.Rows.Count - 1; rowindex > 0; rowindex--)
{
System.Diagnostics.Debug.WriteLine(rowindex);
GridViewRow row2 = ijp_gridview.Rows[rowindex];
GridViewRow previousRow = ijp_gridview.Rows[rowindex - 1];
for (int cellcount = 0; cellcount < 2; cellcount++)
{
if (row2.Cells[cellcount].Text == previousRow.Cells[cellcount].Text)
{
if (row2.Cells[cellcount].RowSpan == 0)
{
previousRow.Cells[cellcount].RowSpan += 2;
}
else
{
previousRow.Cells[cellcount].RowSpan = row2.Cells[cellcount].RowSpan + 1;
}
row2.Cells[cellcount].Visible = false;
}
}
}
It should be look like this but first and second column should rowspan same value. I don't know whats causing the problem I've tried different methods but it ends up distorting the gridview.
Expected gridview layout

Auto Update DropDown items in Datalist in Asp.net

I am Working on a Shop page where I want the Dropdownlist show the available Quantity . (Eg: if stock contains 2 items then Dropdownlist contains Items 1 followed by 2..)
Here's the code I attempted , I have no idea in which event i should put it.
`
Code:
connect cu = new connect();
System.Web.UI.WebControls.Label Label8 = (System.Web.UI.WebControls.Label)DataList1.FindControl("modelnoLabel");
//Modelnolabel contains model no
cu.cmd.CommandText = "select qty from stock where modelno=#mod";
//qty is retrived based on modelnolabel text of datalist
cu.cmd.Parameters.Clear();
cu.cmd.Parameters.AddWithValue("#mod", Label8.Text);
int qty = Convert.ToInt16(cu.cmd.ExecuteScalar());
if (qty < 5 && qty > 0)
{
(DataList1.FindControl("DropDownList1") as DropDownList).Items.Clear();
for (int i = 1; i < qty + 1; i++)
{
(DataList1.FindControl("DropDownList1") as DropDownList).Items.Add(Convert.ToString(i));
}
}
else
{
(DataList1.FindControl("DropDownList1") as DropDownList).Visible = false;
}`
Thanks in advance
Thanks for the silence ,It really helped me figure out on my own :)
protected void DataList1_Load(object sender, EventArgs e)
{
for(int j=0;j<DataList1.Items.Count;j++)
{
System.Web.UI.WebControls.Label Label8 = (System.Web.UI.WebControls.Label)DataList1.Items[j].FindControl("modelnoLabel");
connect cu = new connect();
cu.cmd.CommandText = "select qty from stock where model=#mod";
cu.cmd.Parameters.Clear();
cu.cmd.Parameters.AddWithValue("#mod", Label8.Text);
int qty = Convert.ToInt16(cu.cmd.ExecuteScalar());
if (qty <= 5 && qty > 0)
{
(DataList1.Items[j].FindControl("DropDownList1") as DropDownList).Items.Clear();
for (int i = 1; i < qty+1; i++)
{
(DataList1.Items[j].FindControl("DropDownList1") as DropDownList).Items.Add(Convert.ToString(i));
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).Text = "Only "+qty+" Left";
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).ForeColor = Color.OrangeRed;
(DataList1.Items[j].FindControl("Button1") as System.Web.UI.WebControls.Button).Visible= true;
(DataList1.Items[j].FindControl("Button3") as System.Web.UI.WebControls.Button).Visible= true;
}
}
else if (qty > 5)
{
(DataList1.Items[j].FindControl("DropDownList1") as DropDownList).Items.Clear();
for (int i = 1; i < 6; i++)
{
(DataList1.Items[j].FindControl("DropDownList1") as DropDownList).Items.Add(Convert.ToString(i));
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).ForeColor = Color.GreenYellow;
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).Text = "Available";
(DataList1.Items[j].FindControl("Button1") as System.Web.UI.WebControls.Button).Visible = true;
(DataList1.Items[j].FindControl("Button3") as System.Web.UI.WebControls.Button).Visible= true;
}
}
else
{
(DataList1.Items[j].FindControl("DropDownList1") as DropDownList).Visible = false;
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).Text = "Out of Stock";
(DataList1.Items[j].FindControl("qtylab") as System.Web.UI.WebControls.Label).ForeColor = Color.Red;
(DataList1.Items[j].FindControl("Button1") as System.Web.UI.WebControls.Button).Visible= false;
(DataList1.Items[j].FindControl("Button3") as System.Web.UI.WebControls.Button).Visible = false;
(DataList1.Items[j].FindControl("Label1") as System.Web.UI.WebControls.Label).Visible = false;
}
}
}

Increment values in gridview column

In my gridview which is in update mode, I need to increment a column value.
Ex: In my gridview have 5 rows and three columns. I need to increment the serial number column value by 1. Increment Gridview1.Rows[1].Cells[2] value by 1 up to 5th row. But when I execute the code it will result the output put of all the column same. This is my code.
{
int totalRows = GridView1.Rows.Count;
for (int RowIndex = 0; RowIndex < totalRows; RowIndex++)
{
GridViewRow row = GridView1.Rows[RowIndex];
TextBox txtslno = row.FindControl("txtslno") as TextBox;
int number = int.Parse(TextBox5.Text);
if (GridView1.Rows.Count > 1)
{
for (int i = 0; i < GridView1.Rows.Count - 1; i++)
{
txtslno.Text = (number + 1).ToString();
number++;
}
}
}
}
First I add this
protected void Button33_Click(object sender, EventArgs e) {
if(GridView1.Rows.Count>1)
{
for (int i = 0; i < GridView1.Rows.Count - 1; i++)
{
GridView1.Rows[i].Cells[0].Text = (i + 1).ToString();
}
}
}
But my gridview is in edit mode, so I can't save that values.

Gridview - Summary and Percent Column

I am creating a simple gridview on page.
Data comes from an sql procedure.
Here is how it looks right now:
My first question is how to calculate percentage for "%" columns. Formula is quite simple:
For example in selected cell it should be 15612/238171 * 100%
I'm calculating summary of every row like so:
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="sprawy" runat="server" Text='<%#Sprawy(Eval("sprawy"),1) %>' />
</ItemTemplate>
<FooterTemplate>
<asp:Label ID="sumaSpraw" runat="server" Text='<%#GetSumaSpraw(1) %>' />
</FooterTemplate>
</asp:TemplateField>
This is my code for column in gridview
And this is code for functions:
public Int32[] SumaSpraw = new Int32[4];
public Int32 Sprawy(object arg1, int i)
{
var ilosc = arg1 != DBNull.Value ? Convert.ToInt32(arg1) : 0;
SumaSpraw[i - 1] += ilosc;
return ilosc;
}
public Int32 GetSumaSpraw(int i)
{
return SumaSpraw[i - 1];
}
I would like to know how to calculate value of "%" cells based on summary from one row and cell value.
My second question:
Is it possible to modify view on grid view to display data in group like so:
I've managed to do the first part by adding 2 event listeners to gridview, onRowDataBound and onDataBound.
This is my code to this methods:
protected void GridViewOnRowDataBound(object sender, GridViewRowEventArgs e)
{
int i=0;
if (sender == GridView1)
i = 0;
else if (sender == GridView2)
i = 1;
if (e.Row.RowType == DataControlRowType.DataRow)
{
SumaSpraw[i] += Convert.ToInt32(((Label)e.Row.FindControl("sprawy")).Text);
SumaAdresow[i] += Convert.ToInt32(((Label)e.Row.FindControl("adresy")).Text);
SumaInPost[i] += Convert.ToInt32(((Label)e.Row.FindControl("inpost")).Text);
SumaPoczta[i] += Convert.ToInt32(((Label)e.Row.FindControl("poczta")).Text);
}
if (e.Row.RowType == DataControlRowType.Footer)
{
((Label)e.Row.FindControl("sumaSpraw")).Text = SumaSpraw[i].ToString("N0");
((Label)e.Row.FindControl("sumaAdresow")).Text = SumaAdresow[i].ToString("N0");
((Label)e.Row.FindControl("sumaInPost")).Text = SumaInPost[i].ToString("N0");
((Label)e.Row.FindControl("sumaPoczta")).Text = SumaPoczta[i].ToString("N0");
}
}
protected void GridViewOnDataBound(object sender, EventArgs e)
{
int i = 0;
if (sender == GridView1)
i = 0;
else if (sender == GridView2)
i = 1;
decimal percent = 0M;
foreach (GridViewRow row in ((GridView)sender).Rows)
{
percent = (Convert.ToInt32(((Label)row.FindControl("adresy")).Text) / SumaAdresow[i]) * 100;
((Label)row.FindControl("procentAdresow")).Text = FormatPercent(Math.Round(percent, 2));
percent = (Convert.ToInt32(((Label)row.FindControl("inpost")).Text) / SumaInPost[i]) * 100;
((Label)row.FindControl("procentInPost")).Text = FormatPercent(Math.Round(percent, 2));
percent = (Convert.ToInt32(((Label)row.FindControl("poczta")).Text) / SumaPoczta[i]) * 100;
((Label)row.FindControl("procentPoczta")).Text = FormatPercent(Math.Round(percent, 2));
}
}
protected string FormatPercent(decimal percent)
{
if (percent == decimal.Truncate(percent))
{
return percent.ToString("N0") + "%";
}
else if (percent * 10 == decimal.Truncate(percent * 10))
{
return percent.ToString("N1") + "%";
}
else if (percent*100 == decimal.Truncate(percent*100))
{
return percent.ToString("N2") + "%";
}
else
return percent.ToString("N0") + "%";
}
Third method is used to format output.
But still I'm wondering about second part- how to merge only 2 cells from 2 rows (like in my second screen).
I've done the styling part. Maybe the code isn't looking so awesome, but it works :)
public static void GridViewRowMerger(GridView gridView, int collIndex)
{
for (int rowIndex = gridView.Rows.Count - 2; rowIndex >= 0; rowIndex--)
{
GridViewRow currentRow = gridView.Rows[rowIndex];
GridViewRow previousRow = gridView.Rows[rowIndex + 1];
if (currentRow.Cells[collIndex].Text != previousRow.Cells[collIndex].Text) continue;
if (previousRow.Cells[collIndex].RowSpan < 2)
{
currentRow.Cells[collIndex].RowSpan = 2;
}
else
currentRow.Cells[collIndex].RowSpan = previousRow.Cells[collIndex].RowSpan + 1;
previousRow.Cells[collIndex].Visible = false;
}
}
public static void GridViewRefreshStyle(GridView gridView, int collIndex)
{
int rows = 0;
for (int rowIndex = 0; rowIndex < gridView.Rows.Count; rowIndex++)
{
if (gridView.Rows[rowIndex].Cells[collIndex].RowSpan > 1)
{
for (int i = 0; i < gridView.Rows[rowIndex].Cells[collIndex].RowSpan; i++)
{
gridView.Rows[rowIndex + i].CssClass = rows%2 == 0
? gridView.RowStyle.CssClass
: gridView.AlternatingRowStyle.CssClass;
}
rowIndex += gridView.Rows[rowIndex].Cells[collIndex].RowSpan - 1;
}
else
{
gridView.Rows[rowIndex].CssClass = rows%2 == 0
? gridView.RowStyle.CssClass
: gridView.AlternatingRowStyle.CssClass;
}
rows++;
}
}
So after binding data do GridView I just call those 2 methods like so:
GridView2.DataSource = dSet.Tables[1];
GridView2.DataBind();
GridViewRowMerger(GridView2, 0);
GridViewRefreshStyle(GridView2, 0);

The IListSource does not contain any data sources.during next page is clicked in gridview

Lbl_Username.Text = FirstName + " " + LastName;
if (!IsPostBack)
{
ds = objSun.FetchTravelDetails(userId);
int datasetcount = ds.Tables[0].Rows.Count;
if (datasetcount == 0)
{
dt.Columns.Add("request_ID");
dt.Columns.Add("userId");
dt.Columns.Add("");
dt.Columns.Add("status");
dt.Columns.Add("remark");
dt.Columns.Add("");
for (int i = 0; i < 9; i++)
{
DataRow dr = dt.NewRow();
dt.Rows.Add(dr);
}
GridView_RequisitionManagement.DataSource = dt;
GridView_RequisitionManagement.DataBind();
}
else
{
GridView_RequisitionManagement.DataSource = ds;
GridView_RequisitionManagement.DataBind();
}
}
}
protected void GridView_RequisitionManagement_RowDataBound(object sender, GridViewRowEventArgs e)
{
int datasetcount1 = ds.Tables[0].Rows.Count;
if (datasetcount1 != 0)
{
for (int i = 0; i < GridView_RequisitionManagement.Rows.Count; i++)
{
LinkButton lnk_view = new LinkButton();
lnk_view = GridView_RequisitionManagement.Rows[i].FindControl("LinkBtn_ViewFullDetails_GridView_LeaveManagement") as LinkButton;
int type = Convert.ToInt32(ds.Tables[0].Rows[i]["request_Type"].ToString());
string typeName = "";
string requestId = GridView_RequisitionManagement.DataKeys[i][0].ToString();
string request_userId = GridView_RequisitionManagement.DataKeys[i][1].ToString();
switch (type)
{
case 2:
{
typeName = "Travel Request";
lnk_view.PostBackUrl = "Status_ViewDetails_TravelClaims.aspx?requestId=" + requestId;
break;
}
case 3:
{
typeName = "Other Claims";
lnk_view.PostBackUrl = "Status_ViewDetails_OtherClaims.aspx?requestId=" + requestId;
break;
}
case 4:
{
typeName = "Petty cash";
lnk_view.PostBackUrl = "Status_ViewDetails_PettyCashVoucher.aspx?requestId=" + requestId;
break;
}
case 5:
{
typeName = "Advance";
lnk_view.PostBackUrl = "Status_ViewDetails_AdvanceRequisitions.aspx?requestId=" + requestId;
break;
}
}
GridView_RequisitionManagement.Rows[i].Cells[1].Text = Convert.ToDateTime(ds.Tables[0].Rows[i]["date"].ToString()).ToShortDateString();
GridView_RequisitionManagement.Rows[i].Cells[2].Text = typeName;
}
}
else
{
for (int j = 0; j < GridView_RequisitionManagement.Rows.Count; j++)
{
GridViewRow rows = GridView_RequisitionManagement.Rows[j];
LinkButton lnk_grd_views = (LinkButton)rows.FindControl("LinkBtn_ViewFullDetails_GridView_LeaveManagement") as LinkButton;
lnk_grd_views.Visible = false;
}
}
}
protected void GridView_RequisitionManagement_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView_RequisitionManagement.PageIndex = e.NewPageIndex;
GridView_RequisitionManagement.DataSource = ds;
GridView_RequisitionManagement.DataBind();
}
Hi guys, I need some help here. I'm using the above code to display the details
in the GridView. The DataTable and DataSet are used to populate the GridView. Now I want to do paging in the GridView, but when the next page is clicked it shows the following error:
The IListSource does not contain any data sources
and the next page in the grid shows empty.
Please assist me with this.
It seems as though you are only setting the DataSet 'ds' if it isn't a postback. So when the PageIndexChanging event is run ds is not going to be set to a dataset.
Try moving
ds = objSun.FetchTravelDetails(userId);
Above the if(!IsPostback) line.

Resources