My Grid View is manually data bound (for other things to work). Reading other threads I have to manage my own sorting events.
When clicking a column to sort it on my webpage I get the error:
"Object reference not set to an instance of an object."
The result of this was that table was null, but I cannot see why it is null.
Any ideas?
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable table = GetData();
table.DefaultView.Sort = e.SortExpression + " " + SetSortDirection(e.SortDirection.ToString());
GridView1.DataSource = table;
GridView1.DataBind();
}
.
protected string SetSortDirection(string currentsortDirection)
{
string sortDirection;
if (currentsortDirection == "Ascending")
{
sortDirection = "Descending";
}
else
{
sortDirection = "Ascending";
}
return sortDirection;
}
EDIT:
public DataTable GetData()
{
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;Initial Catalog=DatabaseName;Integrated Security=True");
conn.Open();
string query = "SELECT * FROM tablex WHERE Property='" + Request.QueryString["xxx"] + "'";
SqlCommand cmd = new SqlCommand(query, conn);
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
return dt;
}
Thanks.
DataTable table = BuildInfo_GridView.DataSource as DataTable;
like this u won't get the datasource what u already binded call back end query to get tha datatable or when u r binding the data only store it in view state and get it
Save your sort order in view state
if (ViewState["sortOrder"] != null)
{
ViewState["sortExpression"] = e.SortExpression;
if (ViewState["sortOrder"].ToString().ToUpper() == "ASCENDING")
{
e.SortDirection = SortDirection.Descending;
ViewState["sortOrder"] = SortDirection.Descending.ToString();
}
else
{
e.SortDirection = SortDirection.Ascending;
ViewState["sortOrder"] = SortDirection.Ascending.ToString();
}
}
else
{
ViewState["sortExpression"] = e.SortExpression;
ViewState["sortOrder"] = e.SortDirection.ToString();
}
Related
I am making a GridView and assigning it to the View property of a ListView. The ListView's ItemsSource is bound to an ObservableCollection<Entry>. Entry is a model in my MVVM application, and it contains a List<KeyValuePair<string,string>>. It also has an indexer which fetches the first KeyValurPair<string,string>'s Value property (from the list) which matches the indexer parameter. So it's much like a dictionary.
Now here's how I am making the GridView.
foreach (Column column in category.Columns.Where(c => c.IsVisibleInTable)) {
var gridViewColumn = new GridViewColumn {
Header = column.Name,
DisplayMemberBinding = new Binding($"[{column.Name}].Value")
};
gridView.Columns.Add(gridViewColumn);
}
Column is also a model but that's not really relevant here.
Now I want to tell the GridView to sort based on the first column. But I can't use the DefaultView of the ItemsSource and add a SortDescription to it because SortDescription expects a Property name whereas I am not binding to a property name but instead to an indexer.
So how can I sort based on the second column?
here is sorting algo
iN gridview pass this two parameter aspx
AllowSorting="true"
OnSorting="OnSorting"
private string SortDirection
{
get { return ViewState["SortDirection"] != null ? ViewState["SortDirection"].ToString() : "ASC"; }
set { ViewState["SortDirection"] = value; }
}
protected void OnSorting(object sender, GridViewSortEventArgs e)
{
this.BindGrid(e.SortExpression);
}
here we have to place the code
` private void BindGrid(string sortExpression = null)
{
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * from [test].[dbo].[myform] order by name", conn);
SqlDataAdapter sda = new SqlDataAdapter();
cmd.Connection = conn;
sda.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
if (sortExpression != null)
{
DataView dv = dt.AsDataView();
this.SortDirection = this.SortDirection == "ASC" ? "DESC" : "ASC";
dv.Sort = sortExpression + " " + this.SortDirection;
GridView2.DataSource = dv;
}
else
{
GridView2.DataSource = dt;
}
GridView2.DataBind();
conn.Close();
}
}`
I work in C-sharp on ASP NET 4.
I need to add a sorting function to a column in a GridView. I've set the AllowSorting-property on the GridView to true and added sort expressions to the column.
Unfortunately, the sorting isn't working in the GridView.
Below is my code-behind-file for the column that should be able to sort, but I get the error
CS1502: The best overloaded method match for 'System.Data.DataView.DataView(System.Data.DataTable)' has some invalid arguments
on this line:
DataView sortedView = new DataView(BindData());
Code behind:
string sortingDirection;
public SortDirection dir
{
get
{
if (ViewState["dirState"] == null)
{
ViewState["dirState"] = SortDirection.Ascending;
}
return (SortDirection)ViewState["dirState"];
}
set
{
ViewState["dirState"] = value;
}
}
public string SortField
{
get
{
return (string)ViewState["SortField"] ?? "Name";
}
set
{
ViewState["SortField"] = value;
}
}
protected void gvProducts_Sorting(object sender, GridViewSortEventArgs e)
{
sortingDirection = string.Empty;
if (dir == SortDirection.Ascending)
{
dir = SortDirection.Descending;
sortingDirection = "Desc";
}
else
{
dir = SortDirection.Ascending;
sortingDirection = "Asc";
}
DataView sortedView = new DataView(RetrieveProducts());
sortedView.Sort = e.SortExpression + " " + sortingDirection;
SortField = e.SortExpression;
gvProducts.DataSource = sortedView;
gvProducts.DataBind();
}
protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
if (dir == SortDirection.Ascending)
{
sortingDirection = "Asc";
}
else
{
sortingDirection = "Desc";
}
DataView sortedView = new DataView(RetrieveProducts());
sortedView.Sort = SortField + " " + sortingDirection;
gvProducts.DataSource = sortedView;
gvProducts.PageIndex = e.NewPageIndex;
gvProducts.DataBind();
}
private void BindData()
{
gvProducts.DataSource = RetrieveProducts();
gvProducts.DataBind();
}
private DataSet RetrieveProducts()
{
DataSet dsProducts = new DataSet();
string sql = " ... ";
using (OdbcConnection cn =
new OdbcConnection(ConfigurationManager.ConnectionStrings["ConnMySQL"].ConnectionString))
{
cn.Open();
using (OdbcCommand cmd = new OdbcCommand(sql, cn))
{
........
}
}
return dsProducts;
}
Edit #1
DataView sortedView = new DataView(dsProducts.Tables[0]);
Edit # 2
I have added in aspx page:
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
But If clicked in Column Name I have this new error:
System.IndexOutOfRangeException: Cannot find table 0.
on this line:
Line 100: DataView sortedView = new DataView(dsProducts.Tables[0]);
The DataView class has only three constructors, in which one is default constructor DataView(), second one takes a DataTable as an argument DataView(DataTable), the other one takes four arguments DataView(DataTable, String, String, DataViewRowState).
The DataView constructor expects arguments of any one of these types, but your code has argument of some other type. That's the error.
Your BindData method should return a DataTable object,
//This function should return a Datatable
private void BindData()
{
gvProducts.DataSource = RetrieveProducts();
gvProducts.DataBind();
}
which you can pass into your DataView here.
DataView sortedView = new DataView(BindData());
For your second edit,
System.IndexOutOfRangeException: Cannot find table 0.
on this line:
Line 100: DataView sortedView = new DataView(dsProducts.Tables[0]);
I guess the dataset is empty, the error clearly states that there isn't any table in the dataset at position 0. So check whether your dataset has tables or not. Might be your sql request didn't get any table to fill in the dataset.
Else you might have created a new instance of the dataset.
I need to filter a gridview that retreives filtered data from a table. Therefore I bound the gridview to a dataset. Now i can't seem to find a solution to filter it further.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataSet ds = new DataSet();
SqlConnection myCon = new SqlConnection(connectionstring);
SqlDataAdapter adapter = new SqlDataAdapter(cmd, myCon);
adapter.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
//need to insert code here for filtering GridView1 based on TextBox1.Text
}
Thanks for the help.
Try this:
protected void Button1_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
SqlConnection myCon = new SqlConnection(connectionstring);
SqlDataAdapter adapter = new SqlDataAdapter(cmd, myCon);
adapter.Fill(ds);
DataView view = new DataView();
view.Table = ds.Tables[0];
view.RowFilter = "ColumnName = " + TextBox1.Text.Trim();
GridView1.DataSource = view;
GridView1.DataBind();
}
you have to refactor your code.
Here's a complete sample which handles GridView's paging, sorting(both directions) and filtering(two columns).
// store sorting across postbacks in a ViewState variable
public string SortExpression
{
get
{
if (ViewState["GridSort"]== null)
{
ViewState["GridSort"] = "Column1 ASC";
}
return ViewState["GridSort"].ToString();
}
set { ViewState["GridSort"] = value; }
}
protected void Page_load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
BindGrid();
}
}
Here's the main method that does all (including the filter-function):
private void BindGrid()
{
try
{
var tblData = new DataTable();
var filter1 = TextBox1.Text.Trim();
var filter2 = TextBox2.Text.Trim();
using (var sqlCon = new System.Data.SqlClient.SqlConnection(connectionstring))
{
String sql = String.Empty;
var sqlCmd = new System.Data.SqlClient.SqlCommand();
if (filter1.Length != 0 && filter2.Length != 0)
{
sql = "SELECT Column1,Column2 FROM Table WHERE Column1 LIKE #Column1 AND Column2 LIKE #Column2 ORDER BY {0}";
sqlCmd.Parameters.AddWithValue("#Column1", string.Format("%{0}%", filter1));
sqlCmd.Parameters.AddWithValue("#Column2", string.Format("%{0}%", filter2));
}
else if (filter1.Length != 0)
{
sql = "SELECT Column1,Column2 FROM Table WHERE Column1 LIKE #Column1 ORDER BY {0}";
sqlCmd.Parameters.AddWithValue("#Column1", string.Format("%{0}%", filter1));
}
else if (filter2.Length != 0)
{
sql = "SELECT Column1,Column2 FROM Table WHERE Column2 LIKE #Column2 ORDER BY {0}";
sqlCmd.Parameters.AddWithValue("#Column2", string.Format("%{0}%", filter2));
}
else
{
// no filter, select all
sql = "SELECT Column1,Column2 FROM Table ORDER BY {0}";
}
sqlCmd.CommandText = string.Format(sql, this.SortExpression);
sqlCmd.Connection = sqlCon;
using (System.Data.SqlClient.SqlDataAdapter objAdapter = new System.Data.SqlClient.SqlDataAdapter(sqlCmd))
{
objAdapter.Fill(tblData);
}
}
GridView1.DataSource = tblData;
GridView1.DataBind();
}
catch (Exception)
{
// log
throw;
}
}
Paging:
private void GridView1_PageIndexChanging(object sender, System.Web.UI.WebControls.GridViewPageEventArgs e)
{
this.GridView1.PageIndex = e.NewPageIndex;
BindGrid();
}
Filter-Button-Click:
private void BtnFilter_Click(object sender, System.EventArgs e)
{
BindGrid();
}
Sorting:
protected void GridView1_Sorting(object sender, System.Web.UI.WebControls.GridViewSortEventArgs e)
{
string currentSortColumn = null;
string currentSortDirection = null;
currentSortColumn = this.SortExpression.Split(' ')[0];
currentSortDirection = this.SortExpression.Split(' ')[1];
if (e.SortExpression.Equals(currentSortColumn))
{
//switch sort direction
switch (currentSortDirection.ToUpper())
{
case "ASC":
this.SortExpression = currentSortColumn + " DESC";
break;
case "DESC":
this.SortExpression = currentSortColumn + " ASC";
break;
}
}
else
{
this.SortExpression = e.SortExpression + " ASC";
}
BindGrid();
}
Just converted from VB manually, so i hope there are no remaining errors.
sql = new SqlConnection(Connection.con);
adapter = new SqlDataAdapter(#"select EntryID * from Table where Name like #Name ", sql);
adapter.SelectCommand.Parameters.AddWithValue("#Name", string.Format("%{0}%", textBox1.Text));
dt = new DataTable();
adapter.Fill(dt);
dataGridView1.DataSource = dt;
I am trying Sorting functionality in Grid view but its not working.Can some body help?
Code:
private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
string newSortDirection = String.Empty;
switch (sortDirection)
{
case SortDirection.Ascending:
newSortDirection = "ASC";
break;
case SortDirection.Descending:
newSortDirection = "DESC";
break;
}
return newSortDirection;
}
protected DataSet FillDataSet()
{
string source = "Database=GridTest;Server=Localhost;Trusted_Connection=yes";
con = new SqlConnection(source);
cmd = new SqlCommand("proc_mygrid", con);
ds = new DataSet();
da = new SqlDataAdapter(cmd);
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
return ds;
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable dt = GridView1.DataSource as DataTable;
if (dt != null)
{
DataView dv = new DataView(dt);
dv.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
GridView1.DataSource = dv;
GridView1.DataBind();
}
Here dt is coming null.why? pls help thanks.
EDIT:
enter code here <asp:GridView ID="GridView1" runat="server" CellPadding="4" ForeColor="#333333"
GridLines="None" AllowPaging="true" AllowSorting="true" PageSize="12"
onpageindexchanging="GridView1_PageIndexChanging"
onsorting="GridView1_Sorting">
EDIT(Total code)
public partial class _Default : System.Web.UI.Page
{
SqlConnection con;
SqlCommand cmd;
DataSet ds;
SqlDataAdapter da;
protected void Page_Load(object sender, EventArgs e)
{
}
private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
string newSortDirection = String.Empty;
switch (sortDirection)
{
case SortDirection.Ascending:
newSortDirection = "ASC";
break;
case SortDirection.Descending:
newSortDirection = "DESC";
break;
}
return newSortDirection;
}
protected DataSet FillDataSet()
{
string source = "Database=GridTest;Server=Localhost;Trusted_Connection=yes";
con = new SqlConnection(source);
cmd = new SqlCommand("proc_mygrid", con);
ds = new DataSet();
da = new SqlDataAdapter(cmd);
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
return ds;
}
protected void GetValues(object sender, EventArgs e)
{
FillDataSet();
}
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
int newPagenumber = e.NewPageIndex;
GridView1.PageIndex = newPagenumber;
GridView1.DataSource = FillDataSet();
GridView1.DataBind();
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataSet ds = FillDataSet();
DataTable dt = ds.Tables[0];
if (dt != null)
{
dt.DefaultView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
GridView1.DataSource = dt;
GridView1.DataBind();
}
CODE:
private string GetSortDirection(string column)
{
string sortDirection = "DESC";
string sortExpression = ViewState["SortExpression"] as string;
if (sortExpression != null)
{
if (sortExpression == column)
{
string lastDirection = ViewState["SortDirection"] as string;
if ((lastDirection != null) && (lastDirection == "DESC"))
{
sortDirection = "ASC";
}
}
}
ViewState["SortDirection"] = sortDirection;
ViewState["SortExpression"] = column;
return sortDirection;
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataTable dt = ((DataSet)Session["myDataSet"]).Tables[0];
dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
GridView1.DataSource = dt;
GridView1.DataBind();
}
Because you're setting a DataSet as DataSource and then casting it to DataTable with the operator as.
The 'as' operator in C# is a tentative cast - if it's impossible to cast (types are not compatible) instead of throwing an exception as the direct cast the 'as' operator sets the reference to null.
If you only have one datatable in your dataset then you can get the first element like this:
ds.Tables[0];
... or use the name of the table:
ds.Tables["myTable"];
in your case you can try...
DataTable dt = GridView1.DataSource.Tables[0] as DataTable;
Hope it helps!
EDIT:
with regards to your sorting problem (once you get the datatable):
if (dt != null)
{
dt.DefaultView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
GridView1.DataBind();
}
You can do this because dt is a reference to the exact same object that's already set as DataSource for your grid. It should do the trick - if not there's smt else I am missing (such as we're sorting the wrong table meaning you have more than one table in the DataSet).
EDIT:
had a look at your code. I don't know exactly when GetValues gets fired but I suspect it's causing your problem (I think it might be overriding your sorting or smt along those lines).
If you comment out FillDataSource from getValues and modify your PageLoad to do this:
void Page_Load(Object sender, EventArgs e)
{
// Load data only once, when the page is first loaded.
if (!IsPostBack)
{
Session["myDataSet"] = FillDataSet();
}
}
then in your sort method you retrieve the DataSource like this:
DataTable dt = ((DataSet)Session["myDataSet"]).Tables[0];
Also you can retrieve the DataSet from session in your pagination handler method.
You should also notice an improvement in performance since you're retrieving the stuff form the db just once.
Give it a shot!
In Testing.aspx.cs
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
if (dataset != null)
{
datatable = dataset.Tables[0];
DataView dataView = new DataView(datatable);
dataView.Sort = e.SortExpression;
GridView1.DataSource = dataView;
GridView1.DataBind();
}
}
In Testing.aspx
<asp:GridView ID="GridView1" runat="server"
AllowSorting="True" OnSorting="GridView1_Sorting">
This is my code code for the Page_Load Event
OdbcConnection myConnection;
DataSet dataSet = new DataSet();
OdbcDataAdapter adapter;
//making my connection
myConnection = new OdbcConnection(ConfigurationManager.ConnectionStrings ["ODBC_ConnectionString"].ConnectionString);
adapter = new OdbcDataAdapter("SELECT * from Company", myConnection);
adapter.Fill(dataSet, "MyData");
GridView1.DataSource = dataSet;
Session["DataSource"] = dataSet;
GridView1.DataBind();
This is my code for the PageIndexChanging event and it all works fine.
DataSet ds = new DataSet();
if (Session["DataSource"] != null)
ds = ((DataSet)Session["DataSource"]);
GridView1.DataSource = ds;
GridView1.PageIndex = e.NewPageIndex;
this.GridView1.DataBind();
Now what code do i need to create the Sorting event?
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
?????????????????????????
}
Etienne
I usually do this:
public string SortField {
get {
return (string) ViewState["_sortField"];
}
set {
ViewState["_sortField"] = value;
}
}
public string SortDir {
get {
return (string) ViewState["_sortDir"];
}
set {
ViewState["_sortDir"] = value;
}
}
Put your code to do databinding into another Method because you have to call it during Sort, Paging, and when your page first loads. Call it DoDataBind() for example. Then you have in DoDataBind()
DataTable dt = yourDataSet.Tables[0];
dt.DefaultView.Sort = SortField + " " + SortDir;
GridView1.DataSource = dt.DefaultView;
GridView1.DataBind();
Then your event looks like this:
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e) {
if (e.SortExpression == SortField && SortDir != "desc") {
SortDir = "desc";
}
else {
SortDir = "asc";
}
SortField = e.SortExpression;
DoDataBind();
}
Then in your aspx page you'll need to specify what the SortExpression is. For example something like this:
<asp:BoundField DataField="FIRSTNAME"
HeaderText="First Name" SortExpression="FIRSTNAME" />
You can filter and sort your dataset using:
ds.Tables[0].Select(filterExp, sortExp, etc...);