Copy GridView struture to another GridView - asp.net

I have about 11 GridViews on my page: GridView1, GridView2, ... GridView10 and GridViewActive.
GridView1 to GridView10 are invisible, but GridViewActive is Visible.
Based on different conditions I need to copy structure of one GridView to GridViewActive.
I need to do something like
//common params
SqlDataSource1.SelectParameters["CommonParam1"].DefaultValue = this.commonParam1;
if (reportname = "report1")
{
SqlDataSource1.SelectParameters["Param"].DefaultValue = this.param;
CopyGridViewStructure(GridView1, GridViewActive);
}
else if (reportname = "report2")
{
SqlDataSource1.SelectParameters["AnotherParam"].DefaultValue = this.anotherParam;
CopyGridViewStructure(GridView2, GridViewActive);
}
etc.
// DO OTHER STAFF WITH GRIDVIEWATIVE HERE AND IN OTHER METHODS
And on button click (actually it is a bit more complicated than simple ButtonClick, as it is Ajax which calls Button click, and button is actually invisible for user):
//this block doesn't work for now, because grvActive doesn't have any structure
this.grvActive.DataSource = SqlDataSource1;
this.grvActive.DataBind();
I need to copy only Columns. Have not found sollution for this. GridView doesn't contain Clone method.
EDIT:
GridView1 to GridView10 and GridViewActive are not dynamically created.
Example of GridView:
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" Visible="false">
<Columns>
<asp:BoundField DataField="username" HeaderText="First Name">
<ItemStyle Width="110px"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="usersurname" HeaderText="Last Name">
<ItemStyle Width="110"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="usertype" HeaderText="User Type">
<ItemStyle Width="100px"></ItemStyle>
</asp:BoundField>
<asp:TemplateField HeaderText="Login">
<ItemTemplate>
<asp:Label runat="server" ID="lblLastModifyDate" Text='<%# MyUtility.MyCommon.FormatDate(Eval("logindate").ToString()) %>' />
</ItemTemplate>
<ItemStyle Width="177px"></ItemStyle>
</asp:TemplateField>
</Columns>
</asp:GridView>
Other GridView are very similar, but with different columnnames and datafields. Some of them contains different TemplateField, some doesn't have TemplateFields at all.

I have not found a sollution for copying GridView structure, however, I have found a solution for my problem. Instead of Cloning structure, I am saving GridView ID and then I am using FindControl.
private string GridID
{
get
{
return ViewState["GridID "].ToString();
}
set
{
ViewState["GridID "] = value;
}
}
And then
SqlDataSource1.SelectParameters["CommonParam1"].DefaultValue = this.commonParam1;
if (reportname = "report1")
{
SqlDataSource1.SelectParameters["Param"].DefaultValue = this.param;
// //CopyGridViewStructure(GridView1, GridViewActive);
GridID = "GridView1";
}
else if (reportname = "report2")
{
SqlDataSource1.SelectParameters["AnotherParam"].DefaultValue = this.anotherParam;
CopyGridViewStructure(GridView2, GridViewActive);
GridID = "GridView2";
}
etc.
And when I need to use gridView, I am using FindControl:
GridView grd = (GridView) this.FindControl(GridID);
// actually for my page I am using masterpage and FindControl is a bit more complicated:
GridView grd = (GridView)((ContentPlaceHolder)(this.Controls[0].FindControl("mainContent"))).FindControl(GridID);

I found some solution:
In Source aspx after grid databind:
Session["gridtoexcel"] = yourgrid;
In destination aspx
var grid = ((GridView)Session["gridtoexcel"]);
gridToExcel.Columns.Clear();
foreach (DataControlField col in grid.Columns)
gridToExcel.Columns.Add(col);
gridToExcel.DataSource = grid.DataSource;
gridToExcel.DataBind();
this way i can 'clone' exact grid to another page.
if you need some css style don't forget of add them in destination page

Related

retrieve the value of hidden column of grid view on submit button click

How can I retrieve the value of hidden column of grid view on submit button click. I searched on internet but mostly found methods on row button click.
<asp:GridView ID="GridBilling">
<Columns>
<asp:BoundField Visible="false" DataField="ID"/>
<asp:TemplateField HeaderText="S No." ItemStyle-Width="8%">
<ItemTemplate>
<%#Container.DataItemIndex+1 %>
</ItemTemplate>
</asp:TemplateField>
... other fields ommitted
</Columns>
</asp:GridView>
<br />
<div style="width:100%"><asp:Button ID="btn_SubmitGrid" runat="server" Text="SUBMIT" OnClick="btn_SubmitGrid_Click" /></div>
protected void btn_SubmitGrid_Click(object sender, EventArgs e)
{
int iRowCnt = 0;
foreach (GridViewRow row in GridBilling.Rows)
{
dr = dt_mnthlybilling.NewRow();
dt_mnthlybilling.Rows.Add(dr);
iRowCnt += 1;
}
}
If you set visible to false on the hidden field, then you can't access it in the back-end code. This is because the data doesn't get rendered. However you can do do by accessing the dataKeys. Set the DataKeyNames on GridView. e.g:
<asp:GridView ID="GridBilling" runat="server" DataKeyNames="ID">
Then in code you can retrieve the value as
GridBilling.DataKeys[ROW_INDEX].Value; // This should return an object. I believe you can set to multiple keys (per row).
Alternatively you hide the column with css (on both header and item)
<asp:BoundField DataField="ID" HeaderStyle-CssClass="hidden" ItemStyle-CssClass="hidden" />
Css add:
<style type="text/css">
.hidden
{
display: none;
}
</style>
In back-end code, the bound column can be accessed as
GridBilling.Rows[*ROW_INDEX*].Cells[0].Text; // If you have a html control you can replace text with FindControl("control_name")
Also in your cs code you have a call to NewRow(). If you accessing a row then you should be calling row. eg:
int iRowCnt = GridBilling.Rows.Count;
foreach (GridViewRow row in GridBilling.Rows)
{
// row.Cells[0].Text
dt_mnthlybilling.Rows.Add(row);
}
(It's been years since I've done web forms, so the syntax may be slightly incorrect.)

Extract a BoundField to a Label

I have a DetailsView which works fine using a data access layer and a query string. However, I'd like to extract one of the fields and use it as the text in a label to go above the DetailsView as a title to that page.
Is this possible? And if so, how?
This is an abstract of the DetailsView:
<Fields>
<asp:BoundField DataField="bandname" HeaderText="Band" />
<asp:BoundField DataField="contactname" HeaderText="Contact" />
<asp:BoundField DataField="county" HeaderText="County" />
</Fields>
and the code behind:
if (Request.QueryString.Count != 0)
{
int id = int.Parse(Request.QueryString["bandid"]);
dtvBand.Visible = true;
List<Band> bandDetails = new List<Band> { BandDAL.AnonGetAllBandDetails(id) };
dtvBand.DataSource = bandDetails;
dtvBand.DataBind();
}
What I'd like to do is take the data in the first BoundField row and make it the text of a label. Pseudocode:
Label1.Text = (<asp:BoundField DataField="band")
I would not try to find the text on the DetailsView but in it's DataSource. You could use the DataBound event which is triggered after the DetailsView was databound, so it's ensured that the DataItem exists.
It depends on the Datasource of your DetailsView. Often it is a DataRowView. You have to cast it, then you can access it's column:
protected void DetailsView1_DataBound(Object sender, EventArgs e)
{
DetailsView dv = (DetailsView)sender;
string yourText = (string)((DataRowView)dv.DataItem)["ColumnName"];
Label1.Text = yourText;
}
If it's not a DataRowView use the debugger to see what dv.DataItem actually is.
I managed to achieve what I wanted using:
string titletext = dtvBand.Rows[0].Cells[1].Text.ToString();
dtvBand.Rows[0].Visible = false;
lblBand.Text = titletext;
It takes the first row of the DetailsView, puts it above the rest in a Label so it can be formatted as a header, then hides the first row of the DetailsView.
How about using a TemplateField as what Tim mentioned:
<Fields>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%# Eval("Band") %>' />
</ItemTemplate>
</asp:TemplateField>
</Fields>

How to set disable or readonly in a datagrid view

I have the following datagrid view that is data bound with some data at the DB
I need to load the information in the data grid and make all the textbox in some columns(in the example only comes on but there are many) to be readonly or disable.
<asp:DataGrid ID="grdRequestTypeItem" TabIndex="1" runat="server" CssClass="Grid" AutoGenerateColumns="False"
AllowSorting="True" Visible="true">
<SelectedItemStyle CssClass="GridSelectedItem"></SelectedItemStyle>
<AlternatingItemStyle CssClass="GridAlternatingItem"></AlternatingItemStyle>
<ItemStyle CssClass="GridItem"></ItemStyle>
<HeaderStyle CssClass="GridHeader"></HeaderStyle>
<Columns>
<asp:TemplateColumn HeaderText="Lot Number">
<ItemTemplate >
<asp:TextBox ID="txtLot" runat="server" Width="100%" Text='<%# DataBinder.Eval(Container, "DataItem.Lot") %>' />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
How can I disable that column in the code behind ??
Neither of the following are working
grdRequestTypeItem.Columns[1].IsReadOnly = true;
((BoundField)grdRequestTypeItem.Columns[0]).ReadOnly = true;
((TemplateField)grdRequestTypeItem.Columns[0]).EditItemTemplate = null;
Even if your DataGrid is not in EditMode it displays the TextBox inside the ItemTemplate. Otherwise you use an EditItemTemplate. That's why neither of your solutions work. You have several options:
Put a <asp:Literal> Control into your ItemTemplate
Bind the ReadOnly property of the TextBox to a bool value of your viewModel
from code behind, you have to address the correct control
you could use something like this to reference the textbox within the item template
foreach (GridViewRow row in grdRequestTypeItem.Rows)
{
var txtLot = row.FindControl("txtLot") as TextBox;
txtLog.IsReadOnly = true;
}
You could also use the DataBinding Event on the row instead of looping through the rows like in the answer of #Stealth22
Try this:
<asp:DataGrid ID="grdRequestTypeItem" TabIndex="1" runat="server" CssClass="Grid" AutoGenerateColumns="False" AllowSorting="True" Visible="true"
OnItemDataBound="grdRequestTypeItem_ItemBound">
And then in your code-behind...
protected void grdRequestTypeItem_ItemBound(Object sender, DataGridItemEventArgs e)
{
if((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
{
TextBox txtLot = e.Item.FindControl("txtLot");
if (txtLot != null)
{
txtLot.ReadOnly = true;
}
}
}
Someone can correct me if I am wrong anywhere, as I work more with GridViews than DataGrids, but as far as I know, the principle is the same.

GridView loses column contents during PostBack

I am having an issue with the behavior of a GridView between post backs.
The real problem comes from a TemplateField I define in the markup at column[0] with a child CheckBox control. Things work fine for the first, and second search executions. However, at some point between the second execution and anything that causes a post back there after, I lose the contents of the TemplateField.
Its only the the contents of the column and not the whole column itself that gets removed. The TemplateField is present in the source and shows a formated column at position 0 of the table.
CODE:
protected void ExecuteSearch(object sender, EventArgs e)
{
if (lb_SelectedFields.Items.Count == 0) { return; } //if no selected fields
//Generates custom SQL query based on user inputs and column Selections
BuildQuery(); // sets txbSqlText.Text = to the SQL string
DataTable Table = SqlAdapter.Select(new System.Data.SqlClient.SqlCommand(txbSqlText.Text));
for (int i = gv_SearchResults.Columns.Count - 1; i > 0; i--)
{ gv_SearchResults.Columns.RemoveAt(i); } //removes all the columns except[0]
foreach (ListItem Item in lb_SelectedFields.Items) //adds all the user defined columns
{
//Column object that is able to find the column definition
Column Col = ColumnsBasedOnFocus.FindColumName(Item.Value);
if (Col.Type == "HyperLink") { gv_SearchResults.Columns.Add(CreateHyperLinkField(Col)); }
else { gv_SearchResults.Columns.Add(CreateBoundColumn(Col, true)); } //true is if the column is visable
}
gv_SearchResults.DataSource = Table;
gv_SearchResults.DataBind();
}
ASP.NET:
<asp:GridView ID="gv_SearchResults" runat="server" GridLines="None" CellSpacing="0"
CellPadding="0" AutoGenerateColumns="false" CssClass="TABLE_LIGHTBLUE" Width="100%">
<HeaderStyle CssClass="TABLE_LIGHTBLUE_HEADERROW" />
<Columns>
<asp:TemplateField ItemStyle-Width="30" ItemStyle-Wrap="false">
<HeaderTemplate>
<center>
<asp:Button ID="btn_SelectAll" runat="server" OnClick="SelectAll" Text="All" CssClass="TEXT_SMALL" />
<asp:CheckBox ID="chk_Placeholder" runat="server" Visible="false" /></center>
</HeaderTemplate>
<ItemTemplate>
<center>
<asp:CheckBox ID="chk_Select" runat="server" Visible="true" />
<asp:Label ID="lbl_AssetGID" runat="server" Visible="false" Text='<%# Bind("i_GID") %>' /></center>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Found a link that describes a similar situation.
https://connect.microsoft.com/VisualStudio/feedback/details/104994/templatefield-in-a-gridview-doesnt-have-its-viewstate-restored-when-boundfields-are-inserted#details
They describe a bug in ASP.Net code that fails to properly manage view states with template fields in dynamically generated grid views.
Basically TemplateFields can't be properly restored from ViewState, and if you modify the ASPX-declared columns programmatically, it can't create them from the declarations either.
The only solution I could get working was to create a new class deriving from TemplateField that in the constructor set the ItemTemplate to an ITemplate-derived class, which means having to define the template programmatically instead of declaratively.
You can also rebind the gridview on each postback but that's its own can of worms.

problem in gridview control of user control

My problem is I am setting the datasource from parent page.But if I set disable to certain columns of gridview the event of the controls inside those disabled column template gets fired. Like I have a checkbox in one column, if disable that column from parent page while data binding the check_checked event is being fired.
here my code- user control aspx
<asp:TemplateField HeaderText="Exclude Null" ItemStyle-Width="50px">
<HeaderTemplate>
Exclude Null
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkExNull" OnCheckedChanged="chkExNull_OnCheckedChanged"
AutoPostBack="true" />
</ItemTemplate>
<ItemStyle HorizontalAlign="left" VerticalAlign="Top" />
<HeaderStyle HorizontalAlign="left" VerticalAlign="Top" />
</asp:TemplateField>
.cs file of parent
GridView gvCondition = (GridView)ucCondition.FindControl("gvCondition");
gvCondition.DataSource = ConditionFieldCollection;
gvCondition.Columns[5].Visible = false;
gvCondition.Columns[6].Visible = false;
gvCondition.Columns[7].Visible = false;
gvCondition.Columns[8].Visible = false;
gvCondition.DataBind();
What should I do, and is there any other way through which I can hide some of the columns of grid view control of user control??
Before your DataBind(). write this:
gvCondition.DataBound += new EventHandler(gvwCondition_DataBound);
and write in that method, the code to hide the columns.
Hope that helps.

Resources