I linked my ASPxGridView to a datasource, but whenever the GridView needs to display more than one page of information, the GridView disappears whenever I click on the 'Next Page' arrow. After I run the search again and populate the GridView, the second page of data is displayed.
This same issue happens when I try to sort by a different column or if I try to move columns around. The data on the GridView disappears only to re-appear with the data adjusted the way I wanted when I run the search again.
<dxwgv:ASPxGridView ID="commentsASPxGridView" runat="server"
AutoGenerateColumns="True" IsCallBack="False"
Width="800px" SettingsPager-PageSize="25">
<Columns>
<%-- Some data columns --%>
</Columns>
<SettingsPager PageSize="25"></SettingsPager>
</dxwgv:ASPxGridView>
My datasource for the GridView is a DataTable object.
The ASPxGridView was not being bound to data on every server request. The page was not handling postback and adding a handler in the Page_Load method like so:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
targetASPxGridView.DataBind();
}
// Rest of code
}
allows the GridView to stay visible and maintain data when being resorted or having its columns adjusted.
Related
How do I create editable gridviews with dynamic controls. The following image gives an idea.
On page load, a gridview will be shown with only a single row other than the header. The row contains two dropdownlist, two textboxes and an image button. Once I enter data in the first row, and then press the image button, a new row with these controls will be created, and so on.
How is this possible?
Gridview by default does not provide a simple way of handling the Insert operations.
You will have to perform several steps to handle this.
First of all each gridview column has to be converted to TemplateColumn(TemplateField). Then in the footer template you have to insert your controls(dropdown, textbox etc.)
<asp:TemplateField HeaderText="Item Category">
<%--Define item template--%>
<FooterTemplate>
<asp:DropDownList ID="dropDownListCategory" runat="server"></asp:DropDownList>
</FooterTemplate>
</asp:TemplateField>
...... similarly other footer templates
You have to add the onclick Event for the ImageButton.
protected void imageButtonInsert_Click(object sender, EventArgs e)
{
//Get the gridview row
GridViewRow row = (sender as Control).NamingContainer as GridViewRow;
DropDownList dropDownListCategory = row.FindControl("dropDownListCategory") as DropDownList;
///Similarly you can access the other controls here
//If you are using SqlDataSource then you can add/assign these values to the insert parameters
//Note that, you need to have insertcommand defined for the sql data source with appropreate parameters
SqlDataSource1.InsertParameters.Add("category", dropDownListCategory.SelectedValue);
//Similarly assign the other parameter values
//Call the insert method of the sql data source.
SqlDataSource1.Insert();
//If you are not using data source approach, here you can insert the data to
// database by calling sql command or other ways
//Rebind the gridview.
GridView1.DataBind();
}
This should work, when you have some rows to display in the gridview.
BIG PROBLEM : EMPTY ROWS
The above approach works when you have at least one row in the gridview. But if you do not have any rows, that is for the first time, the gridview will be empty. If the gridview data source is empty, then it does not display anything, even header,footer, rows etc.
As a initial workaround, first you need to make the header is always visible
ShowHeaderWhenEmpty="true" ShowFooter="true"
This makes sure that you have the headers all the time.
Now footer will not at all display unless and until there is some row in the gridview.
As a work around you can use EmptyDataTemplate of the gridview.
Here you need to add all your controls again, dropdownlist, textboxes etc. Not that you have to use here to make the same layout. You can use the same control ids, so that you dont need to write the codebehind again
<EmptyDataTemplate>
<tr>
<td><asp:DropDownList ID="dropDownListCategory" runat="server"></asp:DropDownList></td>
<td><asp:Button runat="server" CommandName="Insert" ID="buttonInsert" OnClick="imageButtonInsert_Click" Text="Insert" /></td>
<%--Other controls go here--%>
</tr>
</EmptyDataTemplate>
This is now good for both first time and successive load.
The next question you may have is how to bind these dropdowns. For this you need to use the RowCreated event, in which you can access the dropdowns and fill them
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Footer || e.Row.RowType == DataControlRowType.EmptyDataRow)
{
DropDownList dropDownListCategory = e.Row.FindControl("dropDownListCategory") as DropDownList;
//similarly access the other controls and bind them
}
}
For Doing this use can use Dynamic table at client side. where you can create whole table dynamically and also apply styling that can look like grid view. for Styling use can use JQuery DataTables which provice much more controls.
And also by using JQuery DataTables or JQuery Code you can also add rows dynamically at client side.
My code is as follows. I am not storing my data in a database. I'm just extracting the data from the TextBox, and displaying it in a GridView. How do I delete multiple rows from a GridView using Checkboxes and a Button?
//code for deleting the row
ASPX Code:
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkdelete" runat="server" />
</ItemTemplate>
</asp:TemplateField>
C# code:
protected void btnDelete_Click(object sender, EventArgs e)
{
//Loop through all the rows in gridview
foreach(GridViewRow gvrow in gvUserDetails.Rows)
{
//Finiding checkbox control in gridview for particular row
CheckBox chkdelete = (CheckBox)gvrow.FindControl("chkdelete");
//Condition to check checkbox selected or not
if(chkdelete.Checked)
{
//code for deleting the row (What code do I write here?)
}
}
}
You have to basically delete the rows in the database or any such thing from where you have bound the gridview. So delete all the rows, create new DataSource and bind the gridview again and it should work like a charm.
UPDATE: As you are not using any database, still you would definitly have some datasource with which you bound your gridview, so modify that and bind the gridview again.
If a GridView works like a DataGridView, then a simple GridView.Rows.RemoveAt(index) should do what you want.
EDIT: In this case, you would not want to do a foreach but a for(int loop=GridView.Rows.Count - 1; loop>=0; loop--), instead.
Problem:
I want to add headers in the middle of a gridview databind. I updated the DataTable to include headers and their correct positions(I've checked during debug, they're there). On the new rows that contain headers, one of the unneeded fields (unneeded as in the header doesn't need that information) has a flag called "Subheader" in it.
Background information:
So my datatable rows hold a server name, and the group the server belongs to. I updated the DataTable so it inserts a new row where the server name is the header text. The server group that this new row belongs to is "Subheader". My datatable holds more information than what my gridview shows. My gridview only needs one column, but has a column with visibility=false; which holds the server group.
What I want to achieve:
So when I bind this datatable to the gridview I want all the non-header rows to be links that point to another location. All the data rows that are headers I want to just leave them as is.
Code:
private void CurrentServers_RowCreated(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if(e.Row.Cells[1].Text != "Subheader")
{
e.Row.Cells[0].Text = "<a href='/EventViewer.aspx?m=" + e.Row.Cells[0].Text + "&s=&e=Application&r=25'>" + e.Row.Cells[0].Text + "</a>";
}
}
}
Questions:
This isn't working. e.Row.Cells[1].Text != "Subheader" always returns true. In debugging I check the value of e.Row.Cells[1].Text and somewhere in there it has the information I need.
Is this the correct event I should be handling?
How do I access that data? e.Row.Cells[1].Text and e.Row.Cells[1].ToString() do not return the result that I want, even though when in debugging I can find the value I want in e.Row
I've tried finding exactly how this works but am unable to find answers. If my GridView only has columns for 2 datatable columns, will e.Row.Cells only have the 2 cells that my gridview requires, or does this take place before it breaks apart the datatable (i.e. does it have all the columns that my datatable has)
Depending on how you bind your data and how you get server group, you could do the following:
In the item template where you're showing content of nonheader row, instead of plain text use two placeholders, one will hold label for nonhyperlink text and another will hold hyperlink. You bind both controls to whatever text property you use. And set those placeholders' visibility to Eval("ServerGroup").ToString().ToLowerInvariant().Equals("subheader") and !Eval("ServerGroup").ToString().ToLowerInvariant().Equals("subheader"). That way you won't have to write code to perform control manipulation and get away from using RowDataBound event all together.
Let me know if this doesn't make sense :)
EDIT:
<asp:GridView ID=".." runat="server" ...>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:PlaceHolder id="phTextContent" runat="server" visible='<%# Eval("ServerGroup").ToString().ToLowerInvariant().Equals("subheader") %>'>
<asp:Label id="lblServerGroup" runat="server" text='<%#Eval("ServerGroup")%>'/>
</asp:PlaceHolder>
<asp:PlaceHolder id="phTextContent" runat="server" visible='<%# !Eval("ServerGroup").ToString().ToLowerInvariant().Equals("subheader") %>'>
<asp:HyperLink id="hlServerGroup" runat="server" Text='<%#Eval("ServerGroup")%>' NavigateUrl='<%#string.Fromat("/MyAction.aspx?param=", Eval("Param"))%>'/>
</asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I'm using GridView to display data from dataBase, the gridView is bound to objectDataSource.
each row in gridview represent an item that belongs to user and I want to add another field to the gridView that will display the users detail (that actually are in a different table at the dataBase).
I'm not sure what is the best way to do that,
I tried to add to the gridView a TemplateField that contain a DetailView,
and bound it to another objectdatasource but I don't know how to take a parameter from a specific field at the row-(the userID field).
Any suggestions would be welcome...
It's going to be a little trickier than that. You can set the userID as a data key, and in the RowDataBound event of the GridView, bind the detail view.
<asp:GridView ID="GridView1" runat="server" DataKeyNames="UserID" OnRowDataBound="GridView1_RowDataBound">
And in the code behind:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//get the data key
int userID = (int)GridView1.DataKeys[e.Row.RowIndex]["UserID"];
//get the nested details view control
DetailsView dv = (DetailsView)e.Row.FindControl("DetailsView1");
dv.DataSource = GetUserDetailsTable(userID); //your data source
dv.DataBind();
}
There are a GridView and a LinqDataSource in a page and few buttons which their actions are not related to the GridView and its LinqDataSource. Why on each post-back of those buttons the Selecting method of the LinqDataSource will call? Is this normal?!
These unwanted db calls from the LinqDataSource are not required.
Is there any better way?
You need to detach the GridView from the data source. I assume you have attached the data source like this, in which case, don't do it this way.
<asp:LinqDataSource
runat="server"
ContextTypeName="AdventureWorksDataContext"
TableName="Contacts"
ID="LinqDataSource1">
</asp:LinqDataSource>
<asp:GridView
ID="GridView1"
runat="server"
DataSourceID="LinqDataSource1" >
</asp:GridView>
Your better off attaching the data source in your code behind when it's needed.
if (dataSourceNeeded == true) {
GridView1.DataSource = GetDataSource();
GridView1.DataBind();
}
it because grid need to populated on every page load, you may cache datasorce to some variable and store it on the server side (not in viewstate)