DevExpress XtraGrid custom RowCellStyle eventhandler and column sorting problem - devexpress

My xtraGrid has a custom style eventlistener:
FooGridView.RowCellStyle += new DevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(FooGridView_RowCellStyle);
private void FooGridView_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
{
DevExpress.XtraGrid.Views.Grid.GridView vw = (sender as DevExpress.XtraGrid.Views.Grid.GridView);
try
{
DataRow DR = vw.GetDataRow(vw.GetRowHandle(e.RowHandle));
if (**some condition based on one or more values in the DataRow**)
{
e.Appearance.Font = new System.Drawing.Font(e.Appearance.Font, System.Drawing.FontStyle.Strikeout);
e.Appearance.ForeColor = Color.LightGray;
}
else
{
e.Appearance.Font = new System.Drawing.Font(e.Appearance.Font, System.Drawing.FontStyle.Regular);
e.Appearance.ForeColor = Color.Black;
}
}
catch (Exception ex) { }
}
After clicking on a grid column header to resort the grid, the formatting ends up applied to the wrong rows after the rows have been reordered by the sort. How to address that problem?

You are taking the e.RowHandle given to you and converting it to a DataSourceHandle. Then, you are calling GetDataRow with the DataSourceHandle.
However, GetDataRow takes in a row handle, not a data source handle. Try this:
DataRow DR = vw.GetDataRow(e.RowHandle);

Related

jqgrid footervalue not correct if rows is empty

I have a jqgrid (ver 4.6.0.0), I show a grant total on footer of a amount column. If user insert a new row or delete a row, it should recalculate the total amount, and show it on footer. It works fine until the grid is empty(no any rows), I mean if user delete the last row on grid, the code still calculate the correct amount ( 0 ), but the footer still show the total amount it was, not 0.
Here is my code:
protected void Jqgrid1_DataRequested(object sender, JQGridDataRequestedEventArgs e)
{
DataSet _ds = (DataSet)Session["myApplicationForm"];
DataTable dt1 = _ds.Tables[1] as DataTable;
CalcVoucherAmt(dt1);
}
private void CalcVoucherAmt(DataTable _dt)
{
decimal amtSum = 0;
foreach (DataRow dr in _dt.Rows)
{
amtSum += obj2decimal(dr["DETAIL_AMT"]);
}
Jqgrid1.Columns.FromDataField("DETAIL_AMT").FooterValue = amtSum.ToString();
}
protected void Jqgrid1_RowAdding(object sender, Trirand.Web.UI.WebControls.JQGridRowAddEventArgs e)
{
DataSet _ds = (DataSet)Session["myApplicationForm"];
DataTable dt1 = _ds.Tables[1] as DataTable;
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["DATA_SEQ"] };
DataRow row = dt1.NewRow();
row["UNIQ_KEY"] = System.Guid.NewGuid().ToString();
row["DETAIL_AMT"] = amt; //user input
dt1.Rows.InsertAt(row, dt1.Rows.Count);
Session["myApplicationForm"] = _ds;
Jqgrid1.DataSource = dt1;
Jqgrid1.DataBind();
}
protected void Jqgrid1_RowEditing(object sender, Trirand.Web.UI.WebControls.JQGridRowEditEventArgs e)
{
DataSet _ds = (DataSet)Session["myApplicationForm"];
DataTable dt1=_ds.Tables[1] as DataTable;
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["DATA_SEQ"] };
DataRow rowEdited = dt1.Rows.Find(e.RowKey);
rowEdited["DETAIL_AMT"] = amt; //user input
Session["myApplicationForm"] = _ds;
Jqgrid1.DataSource = dt1;
Jqgrid1.DataBind();
}
protected void Jqgrid1_RowDeleting(object sender, JQGridRowDeleteEventArgs e)
{
DataSet _ds = (DataSet)Session["myApplicationForm"];
DataTable dt1 = _ds.Tables[1] as DataTable;
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["DATA_SEQ"] };
DataRow rowToDelete = dt1.Rows.Find(e.RowKey);
if (rowToDelete != null)
dt1.Rows.Remove(rowToDelete);
}
and in aspx, the code is
<cc1:JQGrid ID="Jqgrid1" runat="server" Height="100%" Width="100%" AutoWidth="true" PagerSettings-PageSizeOptions="[]"
OnRowAdding="Jqgrid1_RowAdding"
OnRowEditing="Jqgrid1_RowEditing"
OnDataRequested="Jqgrid1_DataRequested"
OnRowDeleting="Jqgrid1_RowDeleting">
</cc1:JQGrid>
any idea?
Why you decide that jqGrid "should recalculate the total amount" automatically? If you insert a row using or delete a row you can specify callback which will be called at the end of Add/Delete operation. Inside of the callback you can use getCol to recalculate the total amount and to use footerData to set new value in the footer.
Alternatively you can trigger reloadGrid which will sort new data correctly, recalculate the total amount and to place it on the footer row. Both ways will work.
The code which you posted seems to have mo relation to jqGrid. It don't show which editing mode and how you use to Add/Delete rows. So I can't give you more detailed implementation tips.

Keeping GridView Column Width the Same

I am populating an ASP.NET GridView manually via C# code and have paging turned on. When a user goes from one page to another the column widths adjust accordingly to what is on the screen. I would like the GridView columns to remain the same no matter which page the user is on (preferably each column is set to the largest character length for its particular column). Can someone suggest the best course of action to accomplish this. Here is how I am populating the GridView
private void BindData(string sortExpression, string sortDirection)
{
db_set_connection_string.set_db_connnection_string(configuration_manager.GetConfigValue("DBSTRING.1"));
db_set_connection_string.set_individual_global_variables(configuration_manager.GetConfigValue("DBSTRING.1"));
sSQLResults = db_connector_mysql.execute_query_with_results_returned("SELECT * From city", false);
//Dynamically create columns
foreach (DataColumn column in sSQLResults.Columns)
{
//So we aren't getting duplicates, we need to check to see if it exists first
if (DoesColumnExistInGridView(column.ColumnName) == false)
{
BoundField nameColumn = new BoundField();
nameColumn.DataField = column.ColumnName;
nameColumn.HeaderText = column.ColumnName;
nameColumn.SortExpression = column.ColumnName;
GridView1.Columns.Add(nameColumn);
}
}
this.GridView1.DataSource = sSQLResults;
if (sortExpression != null)
{
sSQLResults.DefaultView.Sort = sortExpression + " " + sortDirection;
}
this.GridView1.DataBind();
}
There are two ways you can do this. Define width at the time of adding columns dynamically.
//Dynamically create columns
foreach (DataColumn column in sSQLResults.Columns)
{
//So we aren't getting duplicates, we need to check to see if it exists first
if (DoesColumnExistInGridView(column.ColumnName) == false)
{
BoundField nameColumn = new BoundField();
nameColumn.DataField = column.ColumnName;
nameColumn.HeaderText = column.ColumnName;
nameColumn.SortExpression = column.ColumnName;
nameColumn.Width=1;
GridView1.Columns.Add(nameColumn);
}
}
or you can do that in Gird View row data bind event
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e){
e.Rows.Cell[1].width=1;}

accessing selected checkboxes in gridview

i have a gridview in which i am using checkbox in each row. i am trying to access checkbox of each row and trying to find out which checkboxes have been checked.buut when i try to run the below code.the condition always stands to be false and the inner if condition is never reached by the code.kindly help me.thanks in advance.
protected void btn_3id_Click(object sender, EventArgs e)
{
string str = "";
string srr = "";
for (int i = 0; i < GridView1.Rows.Count;i++ )
{
CheckBox chk = (CheckBox)GridView1.Rows[i].FindControl("CheckBox1");
if (chk.Checked==true)
{
if (str == "")
{
str = GridView1.Rows[i].Cells[0].Text.ToString();
}
else
{
srr = str + "," + GridView1.Rows[i].Cells[0].Text.ToString();
}
}
}
Session["Card_id"] = str;
Response.Redirect("ID.aspx");
}
The code looks fine.
The problem could be you are binding the gridview at page load.
Try grid binding in the following section of page load
if(!Page.IsPostBack)
{
//code to bind the gridview
}
I can only guess that you are binding your gridview on each page load without checking PostBack. That is causing the checkbox to loose its current state. So where you are assigning the DataSource to the Gridview , Check for PostBack like:
if(!Page.IsPostBack)
{
GridView1.DataSource = yourDataSource;
GridView1.DataBind();
}
also you can do some minor improvements in your code like your check:
if(chk.Checked == true)
can be replaced as:
if(chk.Checked) //Since it returns a bool value.
You can omit multiple string variables for concatenation. Its better if you use StringBuilder, (See why it is better) so your code would be:
protected void btn_3id_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < GridView1.Rows.Count;i++ )
{
CheckBox chk = (CheckBox)GridView1.Rows[i].FindControl("CheckBox1");
if (chk.Checked==true)
{
sb.Append() GridView1.Rows[i].Cells[0].Text.ToString();
}
}
Session["Card_id"] = sb.ToString();
Response.Redirect("ID.aspx");
}
if(!Page.IsPostBack)
{
//
}
Postback plays important role in cs file. If you are clearing values on page load , you will null values of checkbox.
You code is fine.
Just try to do this...

LinkButton in GridView not picking correct value

I am using link button to display a pdf report for selected Report Id from Grid view. On page load I am binding the datasource with Gridview. By clicking the link button it fetches the correct report id from column 0 and displays the report. After sorting the grid the grid view shows the sorted data. Now if i click the link button it is not picking the changed value from column 0. instead it is picking the value before sorted.
Say: Column 0 has values 1, 2, 3, 4, 5 before sorting. If i click link button of Row 3 before sorting it is picking value 3 from column 0. After sorting it is 3,4,5,2,1. Now if i click link button of row 3 it is still picking value 3 instead of 5. Can you please help me.
Below is my code:
aspx:
CS:
protected void Page_Load(object sender, EventArgs e)
{
bindGrid();
}
protected void GvStockTakingReport_Sort(object sender, GridViewSortEventArgs e)
{
GvStockTakingReport.DataSource = null;
GvStockTakingReport.DataBind();
GvStockTakingReport.Dispose();
DataSet ds = StockTakingList.BindStocktakingReportGrid();
DataTable dtSortTable = ds.Tables[0];
if (dtSortTable != null)
{
DataView dv = new DataView(ds.Tables[0]);
dv.Sort = e.SortExpression + " " + getSortDirectionString();
//ViewState["sortExpression"] = e.SortExpression;
//Session["sortExpression"] = e.SortExpression;
GvStockTakingReport.DataSource = dv;
GvStockTakingReport.DataBind();
}
}
protected void PrintReport(object sender, CommandEventArgs e)
{
LinkButton lkButton = (LinkButton)sender;
GridViewRow item = (GridViewRow)lkButton.NamingContainer;
string Id = (item.FindControl("lblstk_id") as Label).Text;
//Getting value for Id
string Id1 = e.CommandArgument.ToString();
int rowIndex = Convert.ToInt32((string)e.CommandArgument);
//string Id1 = Convert.ToString(GvStockTakingReport.Rows[rowIndex].Cells[0].Text);
string Id2 = ((Label)(GvStockTakingReport.Rows[rowIndex].FindControl("lblstk_id"))).Text;
//Getting value for Id
string virtualPath = string.Format("~/{0}/{1}{2}", Portal.Business, Portal.Core.Profile.ReportsDirectory, "General/RPT_03002_StockTakinReport.rpt");
string physicalPath = Server.MapPath(virtualPath);
using (ReportDocument report = new ReportDocument())
{
report.Load(physicalPath);
Core.Security.CrystalReportLogOn(report, (SqlConnectionStringBuilder)Portal.Core.Profile.ConnectionStrings["MTServer"]);
report.SetParameterValue("#STK_Id", Id);
report.ExportToHttpResponse(ExportFormatType.PortableDocFormat, Page.Response, true, "Stock Taking report");
}
}
the issue was whenever i click the link button the page load calls
bindgrid method which resets the gridview to original sorting before the printreport method invokes.
I have included the sorting logic in bindgrid method as well as below which resolved the issue.
public void bindGrid()
{
try
{
DataSet ds = StockTakingList.BindStocktakingReportGrid();
GvStockTakingReport.DataSource = ds;
GvStockTakingReport.DataBind();
//To make sure the grid remains with sorting order while pageload method invokes otherwise it will reset to original order
DataView dv = new DataView(ds.Tables[0]);
if (dv != null)
{
if (ViewState["sortExpression"] == null)
{
ViewState["sortExpression"] = "STK_Id"; //First time it will sort by STK_ID i.e on first time page loading
}
if (ViewState["sortDirection"] == null)
{
ViewState["sortDirection"] = "ASC";//First time it will sort ascending i.e on first time page loading
}
dv.Sort = ViewState["sortExpression"].ToString() + " " + ViewState["sortDirection"].ToString();
GvStockTakingReport.DataSource = dv;
GvStockTakingReport.DataBind();
}
}
catch (Exception ex)
{
error.Visible = true;
error.Text = ex.Message.ToString();
}
}

is there a convenient way to filter by a group column in XtraGrid GridView without displaying that column?

this is a continuation of my previous question is there off-the-shelf convenient way to filter by a group column in XtraGrid GridView? .
I was told to set GridView.OptionsView.ShowGroupedColumns to true, but that simply sucks. I don't want to waste horizontal space in my grid showing the group columns - it is sufficient to show them as group headers. I only want to have nice filter textboxes for those columns on top.
Any other suggestions short of rolling my own?
XtraGrid cannot show the auto filter editor behind the group column if the corresponding column is not shown in the column header panel. A possible solution is to show an external editor near the grid. One more solution - is to show an editor at the position of the group column header. In this case, you will have to implement filtering and managing the editor yourself. Something like this:
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Drawing;
using DevExpress.Data.Filtering;
private void gridView1_Click(object sender, EventArgs e) {
MouseEventArgs args = e as MouseEventArgs;
GridView view = sender as GridView;
GridHitInfo hitInfo = view.CalcHitInfo(args.X, args.Y);
if(hitInfo.InGroupColumn) {
ShowFilterEditor(hitInfo.Column);
}
}
private void ShowFilterEditor(GridColumn gridColumn) {
GridView gridView = gridColumn.View as GridView;
GridViewInfo vInfo = gridView.GetViewInfo() as GridViewInfo;
for(int i = 0; i < vInfo.GroupPanel.Rows.Count; i++)
for(int j = 0; j < vInfo.GroupPanel.Rows[i].ColumnsInfo.Count; j ++) {
GridColumnInfoArgs columnInfo = vInfo.GroupPanel.Rows[i].ColumnsInfo[gridColumn];
if(columnInfo != null) {
Rectangle columnRect = columnInfo.CaptionRect;
TextEdit edit = new TextEdit();
gridControl1.Controls.Add(edit);
edit.SetBounds(columnRect.Left, columnRect.Top, columnRect.Width, columnRect.Height);
edit.Focus();
edit.KeyPress += new KeyPressEventHandler(edit_KeyPress);
edit.KeyDown += new KeyEventHandler(edit_KeyDown);
edit.Disposed += new EventHandler(edit_Disposed);
edit.Tag = gridColumn;
return;
}
}
}
void edit_Disposed(object sender, EventArgs e) {
TextEdit edit = sender as TextEdit;
edit.KeyPress -= new KeyPressEventHandler(edit_KeyPress);
edit.KeyDown -= new KeyEventHandler(edit_KeyDown);
edit.Disposed -= new EventHandler(edit_Disposed);
edit.Tag = null;
}
void edit_KeyDown(object sender, KeyEventArgs e) {
if(e.KeyCode == Keys.Return)
BeginInvoke(new MethodInvoker(delegate { (sender as TextEdit).Dispose(); }));
}
void edit_KeyPress(object sender, KeyPressEventArgs e) {
BeginInvoke(new MethodInvoker(delegate {
TextEdit edit = sender as TextEdit;
if(edit.IsDisposed)
return;
GridColumn column = edit.Tag as GridColumn;
column.FilterInfo = new ColumnFilterInfo(new BinaryOperator(column.FieldName, string.Format("%{0}%", edit.Text), BinaryOperatorType.Like));
}
));
}

Resources