FormView.DataItem is null on postback - c#

I am using a LinqDataSource and a FormView with paging enabled on an ASP.NET page. I am trying to access the FormView's DataItem property on PageLoad and I have no trouble on the first page load, but as soon as I use the Next/Prev page button (causing a postback) on the FormView the DataItem property is null, even if there a record showing in the FormView. Any ideas why it works fine on the first page load but not on a postback?
If you're curious what my PageLoad event looks like, here it is:
protected void Page_Load(object sender, EventArgs e)
{
Label lbl = (Label)fvData.FindControl("AREALabel");
if (fvData.DataItem != null && lbl != null)
{
INSTRUMENT_LOOP_DESCRIPTION record = (INSTRUMENT_LOOP_DESCRIPTION)fvData.DataItem;
var area = db.AREAs.SingleOrDefault(q => q.AREA1 == record.AREA);
if (area != null)
lbl.Text = area.AREA_NAME;
}
}

The object you bind to any data-bound control won't be persisted in the page's ViewState
Therefore, on subsequent posts the DataItem property will be null unless you re-bind the control
This property will contain a reference to the object when the control is bound.
Usually you would need to access this property if you want to do something when the objects is bound, so you need to react to the DataBound event
Example:
Output
Code behind
protected void ds_DataBound(object sender, EventArgs e)
{
var d = this.fv.DataItem as employee;
this.lbl.Text = d.lname;
}
ASPX
<asp:LinqDataSource ID="lds" runat="server"
ContextTypeName="DataClassesDataContext"
TableName="employees"
>
</asp:LinqDataSource>
<asp:FormView runat="server" ID="fv" DataSourceID="lds" AllowPaging="true"
OnDataBound="ds_DataBound">
<ItemTemplate>
<asp:TextBox Text='<%# Bind("fname") %>' runat="server" ID="txt" />
</ItemTemplate>
</asp:FormView>
<br />
<asp:Label ID="lbl" runat="server" />

Your data will not be preserved on PostBack. You'll need to rebind the FormView in the PageIndexChanging event using something like:
protected void FormView_PageIndexChanging(object sender, FormViewPageEventArgs e)
{
FormView.PageIndex = e.NewPageIndex;
//rebind your data here
}

Related

Access a UserControl in a Gridview from the RowDatBound method

I have a gridview and within the item template i have a usercontrol which is losing it's value on postback. I want to be able to access the control from my RowDataBound method in the c# code behind and reassign the CandidateID value
GridView Control
<asp:TemplateField>
<ItemTemplate>
<Controls:LikeButton ID="CandidateLikeButton" runat="server" LikeType="Candidate"
LikedObjectID='<%# Bind("CandidateID") %>' />
</ItemTemplate>
</asp:TemplateField>
How can i do this?
You can access it with FindControl like any other Control and cast it back to it's type.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LikeButton LB = e.Row.FindControl("CandidateLikeButton") as LikeButton;
LB.CandidateID = 1234;
}
}

How to fetch values inside a parent repeater on link button click?

On a link button click , I want to fetch the value of a hidden field which is contained inside a repeater. Below is my code
aspx page:
<asp:Repeater ID="rpt1" runat="server">
<ItemTemplate>
<asp:LinkButton ID="lnkBtn1" runat="server" OnClick="btnClick"/>
<asp:HiddenField ID="hdn1" runat="server" Value="true"/>
</ItemTemplate>
</asp:Repeater>
CodeBehind:
protected void btnClick(object sender, EventArgs e)
{
//How to get the value of the hidden field hdn1 over here
}
try this
Find Row of repeater from Button as sender then find Hidden field inside (RepeaterItem) repeater row
protected void btnClick(object sender, EventArgs e)
{
LinkButton lnkBtn1= sender as LinkButton;
RepeaterItem Rptitem = (RepeaterItem)lnkBtn1.NamingContainer;
HiddenField hdn1 = (HiddenField ) Rptitem.FindControl("hdn1");
string hiddenvalue=hdn1.Value;
}

How to access the current ItemType Item value from OnItemCommand method of ListView?

In aspx page:
<asp:ListView ID="ListViewPosts" ItemType="Post"
SelectMethod="ListViewPosts_GetData" runat="server"
OnItemCommand="Insert_Comment"
OnItemDataBound="ListViewPosts_ItemDataBound">
...
...
</asp:ListView>
Code behind:
protected void Insert_Comment(object sender, ListViewCommandEventArgs e)
{
...
Post p = Item; //where Item stands for the current Post record in ListView.
...
}
If I have this ListView where in ItemType="Post"; Post is a database table.
How to access the current value of Item (which stands for the current record from thePost table) in the code behind method Insert_Comment
I asked a question for OnItemDataBound method and the code:
Post p = e.Item.DataItem as Post works well. I tried the same code for OnItemCommand but the variable Post p gets null value!!.
I can use CommandArgument but I am wondering if I can get the Post item directly like the way I can with OnItemDataBound methos.
You can use use .DataItem only within OnItemDataBound. You may pass the Id of the Item and use it to bring the Item back from the database:
<asp:ListView ID="ListViewPosts" ItemType="Post"
SelectMethod="ListViewPosts_GetData" runat="server"
OnItemDataBound="ListViewPosts_ItemDataBound">
<ItemTemplate>
<asp:LinkButton runat="server" ID="btn_InsertComment" CommandName="Insert_Comment" CommandArgument='<%# Eval("PostID") %>' Text="Insert" />
</ItemTemplate>
</asp:ListView>
protected void Insert_Comment(object sender, ListViewCommandEventArgs e)
{
LinkButton btn_InsertComment = (LinkButton) sender;
string postId = btn_InsertComment.CommandArgument;
//use this id to create a new comment
}

How to add web user controls to repeater

Scenario:
UsrControl: custom user control, which contains a textbox and a button, rederend horizontally (in one line).
UsrControlContainer: custom user control, which should be able to display multiple UsrControl objects (each object in seperate line, so the Seperator template will probably be <br />. This control also contains a button, which adds new UsrControl to the collection.
My code:
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click"/>
<asp:Repeater ID="rptExample" runat="server">
<ItemTemplate>
</ItemTemplate>
<SeparatorTemplate><br /></SeparatorTemplate>
</asp:Repeater>
And:
protected void Button1_Click(object sender, EventArgs e)
{
rptExample.DataSource = new List<UsrControl> {new UsrControl(), new UsrControl()};
rptExample.DataBind();
}
Simple question - what should I put in ItemTemplate to make this work?
Edit - I also want to pass some parameters to UsrControl before rendering it.
<asp:Repeater ID="rptExample" runat="server">
<ItemTemplate>
<uc:UsrControl runat="server" />
</ItemTemplate>
<SeparatorTemplate><br /></SeparatorTemplate>
</asp:Repeater>
protected void Button1_Click(object sender, EventArgs e)
{
rptExample.DataSource = Enumerable.Range(0, 2);
rptExample.DataBind();
}
Following your question in answer. You can catch every binding object in ItemDataBound event. So for example, as i used, set whole object as user control property.
protected void PersonesRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
PersonLine line = (PersonLine)e.Item.FindControl("Person1");
line.Person = e.Item.DataItem as Osoba;
}
}
Ofcourse, you have to add the event handler to your repeater:
<asp:Repeater runat="server" ID="PersonesRepeater" OnItemDataBound="PersonesRepeater_ItemDataBound"><ItemTemplate>
<my:Person ID="Person1" runat="server" />
</ItemTemplate>
</asp:Repeater>

Manipulating DropDownList within TemplateField

I have a dropdownlist inside of a TemplateField, within a GridView.
I would like to dynamically add list items to it and write code to handle when the index changes. How do I go about manipulating the list, since I can't directly reference the DropDownList when it's in a TemplateField.
Here is my code:
<asp:TemplateField HeaderText="Transfer Location" Visible="false">
<EditItemTemplate>
<asp:DropDownList ID="ddlTransferLocation" runat="server" ></asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
If I'm understanding what you want to do correctly, you can handle adding items to your drop down like this:
foreach (GridViewRow currentRow in gvMyGrid.Rows)
{
DropDownList myDropDown = (currentRow.FindControl("ddlTransferLocation") as DropDownList);
if (myDropDown != null)
{
myDropDown.Items.Add(new ListItem("some text", "a value"));
}
}
Then, if you mean handling the index change of the DropDownList you just need to add an event handler to your control:
<asp:DropDownList ID="ddlTransferLocation" runat="server" OnSelectedIndexChanged="ddlTransferLocation_SelectedIndexChanged" AutoPostBack="true"></asp:DropDownList>
Then in that event handler you can use (sender as DropDownList) to get whatever you need from it:
protected void ddlTransferLocation_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList myDropDown = (sender as DropDownList);
if (myDropDown != null) // do something
{
}
}

Categories