User Control inside Repeater - Values lost on PostBack - RadRating - asp.net

I have a UserControl Inside a repeater, coded in the following way:
ParentPage.aspx:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<uc1:MovieDetailPanel runat="server" myMovieID='<%# Eval("movieID") %>' myMovieName='<%# Eval("movieName") %>'
myMovieDescription='<%#Eval("movieDescription") %>' myMovieImagePath='<%# Eval("posterImage") %>'
myMovieYear ='<%# Eval("movieYear") %>' myMovieGenre ='<%# Eval("movieGenre") %>' myMovieAverageRating ='<%# Eval("movieRating") %>'
myMovieCountry ='<%# Eval("movieCountry") %>' myMovieLanguage ='<%# Eval("movieLanguage") %>'
id="MovieDetailPanel1" />
</ContentTemplate>
</ItemTemplate>
</asp:Repeater>
ParentPage.cs:
private void LoadMyControls()
{
Repeater1.DataSource = new Common().getMoviesList(selectedGenre, selectedYear, selectedPopularity, selectedLanguage, selectedCountry);
Repeater1.DataBind();
}
UserControl.cs:
public int myMovieID { get; set; }
public string myMovieName { get; set; }
public double myMovieAverageRating { get; set; }
//some more properties
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
MovieRatingControl.Value = myMovieAverageRating ;
}
}
I have a Telerik RadRating (ID# MovieRatingControl) in my UserControl. On page load of the UserControl I am setting the value of the rating control, as passed by repeater from Database (wrapped it inside if(!Page.IsPostBack) as shown above. So each movie gets its own rating as present in the database.
However, on postback (when I click the rate button), the RadRating Control loses its value and becomes 0. This happens on all the UserControls inside the repeater and not just the UserControl in which I clicked the Rate button. Can someone please let me know how I am supposed to retain this rating value ? I need to get that and update my DB Tables.
P.S: If im not using if (!Page.IsPostBack), I retain values from DB but not the rating set by the user. The issue is, the rating set by user is not maintained.

Related

Usercontrol in EditItemTemplate of templated control. How to achieve two-way databinding?

I was hoping to replace the EditItemTemplate of an ASP.NET ListView with a user control but I can't work out how to bind it to the data item in the ListView to achieve two-way data binding. The data item isn't a simple property. It's an object.
This seems only to give one-way Eval type databinding:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Container.DataItem %>'/>
</EditItemTemplate>
This gives an error:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Bind("Container.DataItem") %>'/>
</EditItemTemplate>
As does this:
<EditItemTemplate>
<uc:MyUserControl id="thecontrol" runat="server" TheObject='<%# Bind("this") %>'/>
</EditItemTemplate>
Is there some binding expression syntax to give two-way databinding to the current item in an EditItemTemplate?
Edit. This is the user control:
public partial class EditItemUserControl : System.Web.UI.UserControl
{
public TestObject TheObject
{
get
{
return new TestObject() { ID = Int32.Parse(hfID.Value), Name = txtName.Text };
}
set
{
hfID.Value = value.ID.ToString();
txtName.Text = value.Name;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Just for reference. I was doing it wrong. A user control lives in the context of the page where it's rendered so there's no need to set a DataSource on it. In the .ascx file you can just use:
Text = '<%# Bind("MyProperty") %>'
or
Text = '<%# Eval("MyProperty") %>'
where MyProperty is some property of the parent control's DataSource.

Radio button to select one box only....ERROR

Something is wrong with the following code cause I can select more than one radiobutton at the same time.... How can I make the following code select only one radiobutton? Please help.
<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource_BGlist">
<ItemTemplate>
<asp:RadioButton ID="Radio1" GroupName="BG_name" runat="server" Text='<%# Eval("BG_fileName") %>' />
<asp:Label ID="BG_fileNameLabel" runat="server" Text='<%# Eval("BG_fileName") %>' />
</ItemTemplate>
</asp:ListView>
The easiest way to accomplish this is to just wrap your listview in an ASP.NET Panel or GroupBox, and ASP will implement the grouping you want.
Adding a panel doesn't group radio buttons together if they are contained in some sort of repeater. Probably the best solution is to use a RadioButtonList as suggested in Grebets' Answer.
If that doesn't suit your needs you can use javascript to alter the radio buttons after they have been created. The following code will work when added to the bottom of your page:
<script type="text/javascript">
var inputElements = document.getElementsByTagName("input");
for (var inputName in inputElements) {
var input = inputElements[inputName];
if (input.type === "radio") {
input.name = "Group1";
}
}
</script>
The script can be simplified if you are using jQuery.
I think the most effective way will be use RadioButtonList:
<asp:RadioButtonList ID="RadioButtonList1" runat="server" DataTextField="BG_fileName" DataValueField="BG_fileName" DataSourceID="SqlDataSource_BGlist">
</asp:RadioButtonList>
And if you preffer to use datasources in codebehind (like I do):
public class MyClass
{
public string BG_fileName { get; set; }
public MyClass(string bgFileName)
{
BG_fileName = bgFileName;
}
}
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
RadioButtonList1.DataSource = new List<MyClass>
{
new MyClass("test string 1"),
new MyClass("test string 2"),
new MyClass("test string 3")
};
RadioButtonList1.DataBind();
}
}

Repeater and public array as NOT datasource.

I want to using two dataSources with repeater. One is binded to dataSource property so my question is is that possible to f.ex. to also repeat some array of string as public property?
It is possible to bind to a property of your datasource that is also a collection. For example:
class Person
{
List<Phone> Phones { get; set; }
string Name { get; set; }
}
class Phone
{
string Number { get; set; }
}
void Page_Load(...)
{
List<Person> people = GetPeople();
peopleRepeater.DataSource = people;
peaopleRepeater.DataBind();
}
aspx page
<asp:Repeater ID="peopleRepeater" runat="server">
<ItemTemplate>
Name : <%# Eval("Name") %>
Phones: <br/>
<asp:Repeater ID="phonesRepeater" runat="server" DataSource='<%# (Container.DataItem as Person).Phones %>'>
<ItemTemplate>
<%# Eval("Number") %> <br />
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
Most ASP.NET Data controls only will bind to a single data source at a time. It is possible to have nested controls that can be bound to multiple data sources. Some 3rd party controls such as RadGridView are designed to handle multiple datasource binding (e.g. hierachical).

ListView + ObjectDataSource SelectMethod called twice when EnableViewState="false"

Note: This question has been completely modified now that I have a simpler example.
I have set up a sample page which only has a ListView and ObjectDataSource. The first time the page comes up (!IsPostBack), my GetList method is called once. After paging (IsPostBack), the GetList method is called twice--the first time with the old paging values and the second time with the new values.
If I set EnableViewState="true" on the ListView, then the GetList method is only called once. It seems to me that the ListView wants an "initial state", which it either gets from ViewState or by re-running the method.
Is there any way to disable ViewState on the ListView and also prevent SelectMethod from being called twice?
ASPX page:
<asp:ListView ID="TestListView" runat="server" DataSourceID="ODS" EnableViewState="false">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
<asp:DataPager ID="TestPager" runat="server" PageSize="10">
<Fields>
<asp:NumericPagerField />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
<div><%# Eval("Title") %></div>
</ItemTemplate>
</asp:ListView>
<asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount"
TypeName="Website.Test" EnablePaging="true" />
ASPX code-behind:
namespace Website
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public IList<DataItem> GetList(int maximumRows, int startRowIndex)
{
return GetListEnumerable().Skip(startRowIndex).Take(maximumRows).ToList();
}
public IEnumerable<DataItem> GetListEnumerable()
{
for (int i = 0; i < 100; i++)
{
yield return new DataItem { Title = i.ToString() };
}
}
public int GetListCount()
{
return 100;
}
}
public class DataItem
{
public string Title { get; set; }
}
}
Either turn ODS caching on.
<asp:ObjectDataSource ID="ODS" ... EnableCaching="true" />
This way the GetList will be called only when new data is needed. Post backs to pages that already had data retrieved will use the cached version and not call the GetList.
Or move your DataPager out of the ListView and set the PagedControlID property.
Actually you should be using the OnSelecting event.
What happens is that ObjectDataSource calls the method SelectMethod twice
First time it gets the data.
Next time it gets the count.
So I think you have to implement the OnSelecting event
<asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount"
OnSelecting="ods_Selecting">
TypeName="Website.Test" EnablePaging="true" />
and then cancel the event when the ObjectDataSource tries to call the count method.
protected void ods_Selecting(object sender,
ObjectDataSourceSelectingEventArgs e)
{
if (e.ExecutingSelectCount)
{
//Cancel the event
return;
}
}
You can look for full implementation as mentioned in the link below
http://www.unboxedsolutions.com/sean/archive/2005/12/28/818.aspx
Hope this helps.
I had a similar problem where it worked different depending on browser. IE one way and all other browsers one way.. Might not be the same issue as you have.
I solved it this way:
protected void DropDownDataBound(object sender, EventArgs e)
{
// Issue with IE - Disable ViewState for IE browsers otherwhise the dropdown will render empty.
DropDownList DDL = (DropDownList)sender;
if (Request.Browser.Browser.Equals("IE", StringComparison.CurrentCultureIgnoreCase))
DDL.ViewStateMode = System.Web.UI.ViewStateMode.Disabled;
else
DDL.ViewStateMode = System.Web.UI.ViewStateMode.Inherit;
}

ASP.NET - Control Events Not Firing Inside Repeater

This is a absurdly common issue and having exhausted all of the obvious solutions, I'm hoping SO can offer me some input... I have a UserControl inside a page which contains a repeater housing several controls that cause postback. Trouble is, all of the controls inside of the repeater never hit their event handlers when they postback, but controls outside of the repeater (still in the UC) are correctly handled. I already made sure my controls weren't being regenerated due to a missing if(!IsPostBack) and I verified that Request.Form["__EVENTTARGET"] contained the correct control ID in the Page_Load event. I attempted to reproduce the symptoms in a separate project and it worked as it should.
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="NoteListControl.ascx.cs"
Inherits="SantekGBS.Web.UserControls.NoteListControl" %>
<asp:UpdatePanel ID="upNotes" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div class="NoteList" id="divNoteList" runat="server">
<asp:Repeater ID="repNotes" runat="server">
<HeaderTemplate>
<table width="98%" cellpadding="3" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr class="repeaterItemRow">
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="~/Content/images/DeleteIcon.gif"
OnClick="ibRemove_Click" CommandArgument='<%# Container.ItemIndex %>' CommandName='<%# Eval("ID") %>'
CausesValidation="false" AlternateText="Delete" />
<%# Eval("Text") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:PlaceHolder ID="phNoNotes" runat="server" Visible="false">
<div class="statusMesssage">
No notes to display.
</div>
</asp:PlaceHolder>
</div>
</ContentTemplate>
</asp:UpdatePanel>
public partial class NoteListControl : UserControl
{
[Ninject.Inject]
public IUserManager UserManager { get; set; }
protected List<Note> Notes
{
get
{
if (ViewState["NoteList"] != null)
return (List<Note>)ViewState["NoteList"];
return null;
}
set { ViewState["NoteList"] = value; }
}
public event EventHandler<NoteEventArgs> NoteAdded;
public event EventHandler<NoteEventArgs> NoteDeleted;
public event EventHandler<NoteEventArgs> NoteChanged;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
UtilityManager.FillPriorityListControl(ddlPriority, false);
}
}
protected void ibRemove_Click(object sender, ImageClickEventArgs e)
{
System.Diagnostics.Debug.WriteLine("ibRemove POSTBACK"); // This is NEVER hit
}
public void Fill(List<Note> notes)
{
Notes = notes;
RefreshRepeater();
}
private void RefreshRepeater()
{
if (Notes != null && Notes.Any())
{
var sorted = Notes.OrderByDescending(n => n.Timestamp);
Notes = new List<Note>();
Notes.AddRange(sorted);
repNotes.Visible = true;
phNoNotes.Visible = false;
repNotes.DataSource = Notes;
repNotes.DataBind();
}
else
{
repNotes.Visible = false;
phNoNotes.Visible = true;
}
}
}
public class NoteEventArgs : EventArgs
{
public Note Note { get; set; }
public NoteEventArgs()
{ }
public NoteEventArgs(Note note)
{
this.Note = note;
}
}
The code is intentionally missing functionality so just disregard that fact.
Your edited code has residual CommandArgument and CommandName properties; are you actually handling the Repeater.ItemCommand event?
If so, and if your page calls the control's Fill method on postbacks, that would explain it.
This classic ASP.NET hair-tearing problem is explained in these posts: A Stumper of an ASP.NET Question and A Stumper of an ASP.NET Question: SOLVED!
The explanation is a little mind-bending, but the crux of it is that Repeater.DataBind interferes with ASP.NET's ability to determine which repeater button caused a postback.
I found a missing td-tag in the Itemtemplate, sometimes when DOM is incorrect, the updatapanel do strange things.
Just about EVERY time I run into this problem it's because DataBind() is being called when it shouldn't be. This will kill most events from controls inside a repeater. I see you have an !IsPostBack check in your Page_Load... so that's a start. But try putting a breakpoint on repNotes.DataBind() and see if it's getting called when you don't expect it.
Does it work OK outside of an UpdatePanel?
I ran into the same problem. It happened with me if I've ran the DataBind twice. In other words when I populate the repeater control twice (for any reason) the events wont fire.
I hope that helps.

Resources