ASP.NET Gridview with Link button column on Dynamic Grid
The ASP.NET Gridview should have a linked column - 1st column, when clicked should take to another page with the clicked cell value. the Grid is a dynamic one, that is the columns are not fixed, no of columns/ column itself is dynamic. I added a asp control just for the first columns and remaining columns are dynamic, in the code behind and I add the first column "linkbutton" always.
<Columns>
<asp:TemplateField HeaderText="linkbutton">
<ItemTemplate>
<asp:LinkButton ID="linkbutton" runat="server" Text='<%#EVal("linkbutton") %>'
CommandName="ShowDetails" CommandArgument='<%#Eval("linkbutton") %>'>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
linkbutton is part of the datatable, so when I bind the datatable to gridview it appears twice, once for the templatefield and once from the datatable bind. gridview.column().visible=false didnot work as it considers linkbutton as the only column not the datatable columns.
i tried to add the Linkbutton control from code behind that one also didnt work.
I would set the autogeneratecolumns to false, and then use asp:BoundFields in order to show the columns from the datatable, other than the linkbutton, which you are handling with the asp:TemplateField.
You can then use GridView.Columns().Visible to hide/show different columns.
You were not able to use GridView.Columns().Visible with the auto generated columns because they are not added to Columns():
Explicitly declared column fields can be used in combination with
automatically generated column fields. When both are used, explicitly
declared column fields are rendered first, followed by the
automatically generated column fields. Automatically generated column
fields are not added to the Columns collection.
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.
I have a asp:GridView wich in code behind is asigned to a List with Objects.
gwMyGridview.DataSource = test; // test is a list with some objects (two fields)
gwTract.DataBind();
I can add buttons and stuff to the columns, but my data (two columns) are always the last two columns. I know BoundField can be used, but I still get two columns in the end.
How can i do this: column1 = data1, column2 = button, column3 = data.
Now it looks like this: button, data, data
Thanks in advance!
Don't let the GridView to auto generate the columns. To do this, follow these steps:
1- Click on the GridView's Tasks (little arrow on top of the GridView when you click on it) and click on Edit Columns, and uncheck the "Auto-Generate fields" field, or from the Markup set the AutoGenerateColumns property to false
2 - Add your columns manually to the GridView, by either adding them in the previous dialog (Fields) or in the markup, in the exact order you want them to a appear in your GridView:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="data1" HeaderText="Data1" />
<asp:TemplateField HeaderText="CustomColumn"></asp:TemplateField>
<asp:BoundField DataField="data2" HeaderText="Data2" />
</Columns>
</asp:GridView>
After that you can bind normally.
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 have a gridview that is loaded from a DataSet, in which most of the fields are generated through templates.
One of them is an Image that changes according to the value that is returned from the dataset.
Here is an example:
<asp:TemplateField HeaderText="Attention">
<ItemTemplate>
<asp:Image ID="alertFlag" runat="server" ImageUrl='<%# Eval("alertFlag").ToString().Equals("True") ? "~/Images/Warning-32.png" : "" %>' />
</ItemTemplate>
</asp:TemplateField>
Now I have a dropdown list, in which, depending on what is chosen, a new request to the database is made, and new columns are added, but the previous ones must stay.
Should I create a new GridView or how should I add new the new columns, keep them hidden, and then show them when the proper event is fired. this includes loading new data from the database and binding to the gridview. And how would I add the condition above programatically?
Thanks.
I would say that you will use the same gridview and have column with visible set to true or false. I will suggest that you have a property in the code behind such as ShowColumnX which will return true or false based on the dropdown value. In the aspx, you will then bind the visible property to that value such as Visible="<%= ShowColumnX %>"
If your existing column is setup to bind value correctly to a field of your data source, then you dont have to do anything different then what you have already done such as rebinding the data source on postback.
I have a dataGrid(not dataGridView) in which i need to add Checkbox dynamically at the first column. How can i do this.?
In the ItemDataBound event, which fires for each row of the DataGrid, you could dynamically add a control to the first cell. Easier to use a TemplateColumn, but if you want to do it dynamically as you asked, this is how I'd do it.
private void DataGrid1_ItemDataBound(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.AlternatingItem) ||
(e.Item.ItemType == ListItemType.Item))
{
CheckBox chk = new Checkbox();
e.Item.Cells[0].Controls.Add(chk);
}
The following woprks with a GridView, and I believe that it's also the same for a DataGrid.
Just add a Template Column. (You can do that in source or via the GUI). Then add a checkbod to the ItemTemplate:
<Columns>
<asp:TemplateField>
<HeaderTemplate>
Retry
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
ps. Might want to consider dropping in a GridView if you're on 2.0+
I don't believe you can add them to the first column dynamically if the datagrid already has columns, because it would just append the new column to a datagrid by using the Add method, making it the last column:
CheckBoxColumn checkCol = new CheckBoxColumn();
DataGrid1.Columns.Add(checkCol);
but to add them dynamically you could either follow thse steps at CodeProject Adding a CheckBox column to your DataGrid
or
If you still want the look of them being in the first column, then you can just create them in your client side code and set their visibile attribute to false and when you conditions are met in code behind then set the attribute to true, which gives the idea that it was crated dynamically