I have a grid on my XtraReports and i would like to place in a conditional page break my list consist of oranges, Lemons and Apples and their descriptions. how do i iterate through each row and get a Field value for particular column.
i have tried accessing the detail Report which is my grid table name and Get Current Column Value but that is not what i am looking for because row 1 will have apple and row 2 will have lemons so i want to break each time when row 1 column 1 does not match row 2 column 1
private void xrPageBreak1_BeforePrint_1(object sender,
System.Drawing.Printing.PrintEventArgs e)
{
SetBreaks(sender);
}
private void SetBreaks(object sender)
{
XRPageBreak control = sender as XRPageBreak;
var ItemName =
DetailReport.GetCurrentColumnValue("Item").ToString();
if(ItemName == "Apple")
{
control.Visible = true;
}
}
the code above returns "Apple"
My issue is related to an earlier question on stackoverflow.
In my previous question I needed to merge columns with the same values in a c# asp.net Gridview Control. This problem was resolved by the excellent help and support from other stackoverflowers, however I'm also required to sort the order on row level e.g:
Current format:
The gridview control allows me to sort values by columns (top to bottom) however would there be a way to sort the rows, e.g: left to right on row level, if you take a look at the (Current format) screenshot and check row 3, you will see the following result: ( 2a, 2c, 2x2a, 2c ) Now ideally I would like to group these together as in ( 3x2a, 2x2c ), but not sure if this would be the correct approach as it would involve shifting the whole column, and I could imagine that if we sort the first row correctly and go to the second row, we might mess up the first row result again, not sure if this would work or even possible.
I would like to have my gridview control displaying the data as following:
Required format:
Would this be the approach or achievable in a asp.net gridview control?
How would I be able to achieve the ideal solution otherwise?
If you need any additional information, please ask and i will try to expand my question.
UPDATED INFORMATION:
After ConnersFan's suggestion, I got the following result, the idea is sort of there, but not quite yet.
After running the page i get this screenshots, after each screenshot i will explain what happens:
^^^ DEFAULT PAGE LOAD: This merges/groups the equal values in the row cell together.
^^^ After clicking on the first row 'sort' link, the first row looks correct, the column header and values are all moving to the correct place.
^^^ After clicking on the second row 'sort' link, it sorts the second row correctly and has not messed up the first row
^^^ After clicking on the third row 'sort' link, it messes up the first and second row, but managed to merge and group the third row ok.
^^^ After clicking on the fourth row 'sort' link, it messes up the first, second and third row, but managed to merge and group the fourth row ok.
^^^ After clicking on the fifth row 'sort' link, (which should not make a difference as they are all the same equal value, it messes up the first, second, third and fourth row, but managed to merge and group the fifth row still ok.
^^^ After clicking on the sixth row 'sort' link, (which should not make a difference as they are all different values, it messes the rest up.
So, what i would love to see is that, we dont need to sort these with a button but just on page load all rows are correctly merged and grouped, without messing up the previous row and we should end up, if done correctly, with the required format screenshot, so the order of the columns is determined by the values in the row cells, if they are equal.
Thank you guys ever so much, you have helped me out greatly already.
If I understand your question correctly, you want to transpose the usual sort command, so that it rearranges the GridView columns according to the order in a row rather than rearranging the rows according to the order in a column.
You can insert a LinkButton in the first column to trigger the sort on a specific row (I used a TemplateField instead of a ButtonField in order to set the text with a binding expression):
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true"
OnRowCommand="GridView1_RowCommand" OnPreRender="GridView1_PreRender">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" Text='<%# "Row " + ((Container as GridViewRow).RowIndex + 1) %>' CommandName="SortRow" CommandArgument='<%# (Container as GridViewRow).RowIndex %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
In code-behind, you can define the number of fixed columns at the left of the grid, and a sortRowIndex variable which is set in the RowCommand event handler:
private const int fixedColumnCount = 1; // Row number column
private int sortRowIndex = -1;
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "SortRow")
{
sortRowIndex = Convert.ToInt32(e.CommandArgument);
// Here set the data source and bind the data to the GridView
GridView1.DataSource = ...
GridView1.DataBind();
}
}
The sort itself could be performed in the data source, as suggested by fnostro in your previous post. Since I don't know what the data looks like, here is one way to do it in the grid.
The work can be done in the PreRender or in the DataBound event of the GridView. The code to group the cells with the same content, given in your other post, should be moved in this event handler as well, and placed after the sort operations.
protected void GridView1_PreRender(object sender, EventArgs e)
{
List<int> sortedColIndexes = null;
if (sortRowIndex >= 0)
{
// Gather the cell data on the sorted row...
List<KeyValuePair<string, int>> cellsToSort = new List<KeyValuePair<string, int>>();
sortedColIndexes = new List<int>();
GridViewRow sortedRow = GridView1.Rows[sortRowIndex];
for (int i = fixedColumnCount; i < sortedRow.Cells.Count; i++)
{
TableCell cell = sortedRow.Cells[i];
cellsToSort.Add(new KeyValuePair<string, int>(cell.Text, i));
}
// ... and sort the cell indexes according to the cell content
sortedColIndexes = cellsToSort.OrderBy(x => x.Key).Select(x => x.Value).ToList();
}
RearrangeRowCells(GridView1.HeaderRow, sortedColIndexes);
foreach (GridViewRow row in GridView1.Rows)
{
RearrangeRowCells(row, sortedColIndexes);
// The code below is taken from the other post
// It merges the cells with the same content
for (int i = 0; i < row.Cells.Count - 1; i++)
{
TableCell cell = row.Cells[i];
if (cell.Visible)
{
int colSpanValue = 1;
for (int j = i + 1; j < row.Cells.Count; j++)
{
TableCell otherCell = row.Cells[j];
if (otherCell.Text == cell.Text)
{
colSpanValue++;
otherCell.Visible = false;
}
else
{
break;
}
}
if (colSpanValue > 1)
{
cell.ColumnSpan = colSpanValue;
cell.BackColor = System.Drawing.Color.Beige;
cell.HorizontalAlign = HorizontalAlign.Center;
}
}
}
}
}
// Utility function which performs the cell permutations on a given row
private void RearrangeRowCells(GridViewRow row, List<int> sortedColIndexes)
{
if (sortedColIndexes != null)
{
List<TableCell> sortedCells = new List<TableCell>();
foreach (int cellIndex in sortedColIndexes)
{
sortedCells.Add(row.Cells[cellIndex]);
}
for (int i = fixedColumnCount; i < sortedCells.Count - 1; i++)
{
row.Cells.Remove(sortedCells[i]);
row.Cells.AddAt(i + fixedColumnCount, sortedCells[i]);
}
}
}
I am trying to import csv to mssql using c# code on a asp.net application.
the below c# code helps to load the csv file, choose the table to import to
and then a button click event matches columns and populates a gridview (dgvmatchdata)
the gridview has two columns where the left side column lists all the available table headers from db
and right side column lists all the csv headers in a drop down list.
now, there are 3 conditions
1. both table and csv has equal no. of column headers.
2. table has more columns than csv
3. csv has more columns than table.
i have successfully finished the first two scenarios. and now, i am stuck at the 3rd scenario
my approach to this is,
for example lets consider the table as 10 columns and csv has 15 columns.
i wish to create 15 rows in dgvmatchdata and display the 10 table column headers on the left side
on their own labels for each. the equivalent righ side of the dgvmatchdata will have a drop down list
which contains 'ignore this column' + 15 columns headers from the csv. so, the ddl will now have 16 items.
i want to place text box for the remaining 5 rows on the table column side and i want to populate
the text box with dropdown list. selected items.text during dropdown selected item change event.
now after i have successfully got text inside the remaining 5 text boxes i will write a code on a button click event
to alter table in the db and then the next step would simply import the csv data to the altered table flawlessly.
the point where i am seeking help is, i have placed the text box correctly but the text box disappears on ddl.selecteditem changed
due to post back issue and i am unable to get the text inside the text box.
kindly help.
Gridview Code
protected void dgvmatchdata_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataTable dt = (DataTable)Session["importcsv"];
string[] csvcolNames = (from dc in dt.Columns.Cast<DataColumn>() select dc.ColumnName).ToArray();
string tablename = ddltable2.SelectedItem.Text;
string[] dbcolNames = loadDataBaseColumns(tablename);
int dbcol = dbcolNames.Length;
int csvcol = csvcolNames.Length;
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Find the DropDownList in the Row
DropDownList ddlcsvcolumns = (e.Row.FindControl("ddlcsvcolumns") as DropDownList);
ddlcsvcolumns.DataSource = csvcolNames;
ddlcsvcolumns.DataBind();
ddlcsvcolumns.Items.Insert(0, new ListItem("Please select"));
}
for (int i = 0; i < dgvmatchdata.Rows.Count; i++)
{
DropDownList ddlselect = dgvmatchdata.Rows[i].FindControl("ddlcsvcolumns") as DropDownList;
foreach (string col in csvcolNames)
{
string tablcol = ((Label)dgvmatchdata.Rows[i].FindControl("lblcolumns1")).Text;
if (tablcol == col)
{
ddlselect.SelectedItem.Text = col;
ddlselect.Enabled = false;
dgvmatchdata.Rows[i].Cells[1].BackColor = System.Drawing.Color.SpringGreen;
}
}
}
}
Drop Down Selected Index Changed
protected void ddlcsvcolumns_SelectedIndexChanged(object sender, EventArgs e)
{
for (int i = 0; i < dgvmatchdata.Rows.Count; i++)
{
string selectcolumns = ((DropDownList)dgvmatchdata.Rows[i].FindControl("ddlcsvcolumns")).SelectedItem.Text;
Label selectlabel = (dgvmatchdata.Rows[i].FindControl("lblColumns") as Label);
TextBox txtcol = (TextBox)dgvmatchdata.Rows[i].FindControl("txtDynamicText" + i.ToString());
if (selectcolumns.Equals("Please select"))
{
selectlabel.Text = "";
}
else
{
selectlabel.Text = selectcolumns;
}
}
}
I have defined a datagridview with 5 columns and another with 1 column ..what i want to do it is on the click of the button in the datagridview with the columns, the row with the single column of the other datagridview pops up..is it possible?..this is the screenshot of my datagridview..
i want to add a datarow of another datagridview with only one column..i know how to handle cellevent but what i really want is the addition of datarow with only one column..
Hope this helps:
private void dgv1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 3)
{
int newRow = dgv2.Rows.Add();
dgv2.Rows[newRow].Cells[0].Value = dgv1.Rows[e.RowIndex].Cells["Stringtext"].Value;
}
}
This should take the value from the StringText cell and place it in the first column of a newly created row in the second grid when the button in cell 4 is clicked in the first grid.
EDIT:
private void dgv1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 3)
{
dgv1.Rows[e.RowIndex].Cells["Stringtext"].Value = dgv2.Rows[{y}].Cells[0].Value;
}
}
This one should set the value of the cell "StringText"(which can be changed to whatever you need it to be) in dgv1 to the value of the cell in dgv2 with the rowIndex {y}.
I have one DataTable like this:
Attribute Percentage ReferenceAmount TaxAmount
------------ ------------ ---------------- -----------
Sales 5.00 5000 250
VAT 2.00 250 5
Discount 0 0 100
I want to Bind this DataTable with one GridView.
But in the GridView, I dont want to display 0. Instead of Zero, I just want leave that cell as empty. I dont want to display any other thing if that contains Zero.
How to replace EmptyString instead of Zero in the DataTable?
I am answering the question late, I know the answer is already accepted. But in the accepted answer, you are iterating the rows after databinding and then setting the value.
It would be better to replace the value at DataBinding time. It will over come the extra overhead of the iteration of the gridview rows.
You can use the RowDataBound event of the GridView. Here is the complete code..
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
System.Data.DataRow dr = ((System.Data.DataRowView)e.Row.DataItem).Row;
if (dr["Percentage"].ToString() == "0")
{
((Label)e.Row.FindControl("lblPercentage")).Text = "";
//this is template field
//OR---If you don't use template field you can do like..--
e.Row.Cells[1].Text = "";
}
}
}
The following GridView DataBound method will loop through every cell in the GridView and replace "0" with an empty string:
protected void GridView1_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
for (int i = 0; i < row.Cells.Count - 1; i++)
{
if (row.Cells[i].Text == "0")
{
row.Cells[i].Text = "";
}
}
}
}
you could easily add an property called PercentageDescription as String
public string PercentageDescription
{
return Percentage == 0 ? " " : Percentage.ToString();
}