I have an outer listview and inside its itemtemplate an inner listview. Each has its own SQLDataSource. A Id field from the outerlistview works as a select parameter for the second listview.
When stepping through with the debugger it works perfectly, unfortunately the rendered page only contains data from the outer listview. It appears the databinding of the outer listview fires and renders the page (including the inner listview) before the codebehind can provide a where parameter to the second listview.
The aspx page is below.
<%# Page Title="Nested ListView" Language="VB" MasterPageFile="~/MasterPages/SimpleMasterPage.master"
CodeFile="NLV2PA_A.aspx.vb" Inherits="Demos_NLV2PA_A" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:ListView ID="ListView1" runat="server" ItemPlaceholderID="PlaceHolder1" DataKeyNames="Id"
DataSourceID="SqlDataSource1">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</LayoutTemplate>
<EmptyDataTemplate>
<span>ListView 1 No data was returned. </span>
</EmptyDataTemplate>
<ItemTemplate>
<span style="">Id:
<asp:Label ID="IdLabel" runat="server" Text='<%# Eval("Id") %>' />
<br />
Name:
<asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
<br />
<br />
</span>
<asp:ListView ID="ListView2" runat="server" ItemPlaceholderID="PlaceHolder2" DataSourceID="SqlDataSource2">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="PlaceHolder2"></asp:PlaceHolder>
</LayoutTemplate>
<EmptyDataTemplate>
<span>ListView2 No data was returned. </span>
</EmptyDataTemplate>
<ItemTemplate>
<span style="">Title:
<asp:Label ID="TitleLabel" runat="server" Text='<%# Eval("Title") %>' />
<br />
<h1>
<%# Eval("Title") %></h1>
<br />
Summary:
<asp:Label ID="SummaryLabel" runat="server" Text='<%# Eval("Summary") %>' />
<br />
PhotoAlbumID:
<asp:Label ID="PhotoAlbumIdLabel" runat="server" Text='<%# Eval("PhotoAlbumId") %>' />
<br />
<br />
</span>
</ItemTemplate>
</asp:ListView>
</ItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:RenaissanceConnectionString1 %>"
SelectCommand="SELECT [Id], [Name] FROM [PhotoAlbum] ORDER BY [Id]"></asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:RenaissanceConnectionString1 %>"
SelectCommand="SELECT [Title], [Summary], [PhotoAlbumId] FROM [Apartments] WHERE ([PhotoAlbumId] = #PAId)">
<SelectParameters>
<asp:ControlParameter ControlID="ListView1" DefaultValue="0" Name="PAId" PropertyName="SelectedValue"
Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
</asp:Content>
The code behind is
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ListView1.ItemDataBound
If e.Item.ItemType = ListViewItemType.DataItem Then
SqlDataSource2.SelectParameters("PAId").DefaultValue = DirectCast(e.Item.FindControl("IdLabel"), Label).Text
End If
End Sub
The output to the browser is:
Id: 8
Name: First set of Photos
ListView2 No data was returned.
Id: 9
Name: Second set of Photos
ListView2 No data was returned.
etc.
Microsoft make the point in an old article that:
You could, in theory, intercept the
ItemDataBound event of the parent
ListView, walk your way through the
control tree, grab a reference to the
child ListView, and bind it
programmatically to data. If you do,
you won't throw an exception, but the
binding command on the inner ListView
is lost because it fires too late to
affect the rendering.
Unfortunately, they don't tell me how to fix it.
If there is any genius out there who could tell me how to get this to work it would be much appreciated.
Put your SqlDataSource2 inside the ItemTemplate of ListView1.
for your ControlParameter, set ControlID="IdLabel" and PropertyName="Text"
You wont need any code behind
Related
I have this html markup:
<div id="profil_rating_container">
<div id="profil_rating">
<div id="pr">
<h2 id="rating" class="profil_rating_title">Hodnocení <asp:Label ID="lblAddRating" runat="server"><span><i class="fa fa-plus-circle"></i></span></asp:Label></h2>
<ajaxToolkit:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"></ajaxToolkit:ToolkitScriptManager>
<ajaxToolkit:Rating ID="FinalRating" runat="server" MaxRating="5" ReadOnly="true" StarCssClass="ratingStar" WaitingStarCssClass="savedRatingStar" FilledStarCssClass="mainFilledRatingStar" EmptyStarCssClass="mainEmptyRatingStar" />
<br />
<asp:SqlDataSource ID="RatinSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:SportovniPlanetaCS %>"
SelectCommand="SELECT [RatingText], [RatingCount], [Name] FROM [rating] WHERE ([ProfileId] = #ProfileId) AND ([RatingText] IS NOT NULL)">
<SelectParameters>
<asp:QueryStringParameter Name="ProfileId" QueryStringField="id" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
<asp:Repeater ID="RatingRepeater" DataSourceID="RatinSqlDataSource" runat="server" OnItemDataBound="RatingRepeater_ItemDataBound">
<ItemTemplate>
<h4><asp:Literal ID="RatingName" runat="server" Text='<%# Eval("Name") %>' /></h4>
<p class="p_rating"><asp:Literal ID="RatingText" runat="server" Text='<%# Eval("RatingText") %>'></asp:Literal></p>
</ItemTemplate>
<FooterTemplate>
<asp:Label ID="lblRating" runat="server" Text="Uživatel zatím nemá žádné hodnocení." Visible="false"></asp:Label>
</FooterTemplate>
</asp:Repeater>
</div>
</div>
</div>
And when I am accesing Ajax Control Toolkit Rating from code behind like this: FinalRating.CurrentRating = cmdRating.ExecuteScalar it underline FinalRating with error text: 'Final Rating' is not declared. It may be inaccessible due to its protection level.
I don't know why this is happening. I have the same code in other 5 pages and it is working finec, but in this one page it isn't. Also when I add new page and add Ajax Rating, I cannot access it from code behind. The rating control isn't in any data component like repeater or datalist. Can this be solved by FindControl? If yes, how exactly?
Does anyone know, what is causing this problem? Thanks for answer.
I need help, I have a DataPager inside the update panel and and working well, but when I refresh page or going on back button form some other page DataPager reset always to the first page.
For example if I was on the tenth page and refresh page, data pager reset to first.
Is there any way to keep the current page on data pager?
My code is:
<asp:SqlDataSource ID="SqlDataSource1" EnableCaching="True" CacheDuration="4000" CacheExpirationPolicy="Sliding"
runat="server" ConnectionString="<%$ ConnectionStrings:blabla %>" SelectCommand=""></asp:SqlDataSource>
<asp:UpdatePanel ID="UpdatePanelnajgornji" runat="server" >
<ContentTemplate>
<asp:ListView ID="ListView1" runat="server" ondatabound="ListView1_DataBound" DataSourceID="SqlDataSource1">
<ItemTemplate>
<asp:HyperLink ID="HyperLink2" Visible='<%# !(Eval("Slika") is DBNull) %>' runat="server" NavigateUrl='<%# Eval("Link") %>' title='<%# Eval("Naslov") %>'>
<asp:Image ID="Image1" runat="server" AlternateText='<%# Eval("Naslov") %>' ImageUrl='<%# Eval("Slika") %>' /></asp:HyperLink>
</ItemTemplate>
</asp:ListView>
<br />
<asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1">
<Fields>
<asp:NextPreviousPagerField />
</Fields>
</asp:DataPager>
</ContentTemplate>
</asp:UpdatePanel>
Browser refresh creates new objects (and thus clears the state of the DataPager). You need to save the current page either in the Session or the ViewState, then initialize the control using those values if they exist in the codebehind. Store the values in an unload event listener.
I need my own posts and comment on the page in my project, something similar to Facebook. I succesfully created posts by using sql table, sqldatasource and repeater. But I have a problem with comments.
I created sql table Comments, there is a column with Post ID. This is my code:
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:MotWebConnectionString %>"
SelectCommand="SELECT * FROM [Posts]
JOIN [Users] ON [Users].[UserName] = [Posts].[UserName]
JOIN [Comments] ON [Comments].[PostId] = [Posts].[PostId]
WHERE ([GroupId] = #GroupId) ">
<SelectParameters>
<asp:QueryStringParameter Name="GroupId" QueryStringField="id" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource3" >
<ItemTemplate>
<table style="width: 100%;">
<tr>
<td width="10%">
<asp:Image ID="Image2" runat="server" Width="64px" Height="64px" ImageUrl='<%# Eval("ProfilePicture")%>' />
</td>
<td align="left" width="90%" >
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("UserName", "~/_/Profile.aspx?Username={0}")%>'><p><asp:Literal ID="Literal2" runat="server" Text='<%# Eval("Username")%>'></asp:Literal></p></asp:HyperLink>
</td>
</tr>
</table>
<asp:Literal ID="Literal3" runat="server" Text='<%# Eval("Text")%>'></asp:Literal>
<br />
<asp:Literal ID="Literal4" runat="server" Text='<%# Eval("CommentText")%>'></asp:Literal>
<asp:FormView ID="FormView2" runat="server" DataSourceID="SqlDataSource4" DefaultMode="Insert" >
<InsertItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" CommandName="Insert" />
</InsertItemTemplate>
</asp:FormView>
</ItemTemplate>
<SeparatorTemplate>
<br />
<br />
<br />
</SeparatorTemplate>
</asp:Repeater>
But it shows only posts, where is at least 1 comment and if there are more comments than 1, the posts is twice or more times on the page.
And another problem is, that I don't know how to insert right Post ID into the Comments table. It is probably by using Parameter...
My database schema (I did't know how to create it in SQL Management Studio, so it is in VS):
http://img685.imageshack.us/img685/1416/vstiekd.jpg
Please could anyone help me with this:
How to view right comments under the post and view also posts without any comment
How to insert the comment with right Post ID
I will be very thankfull for any kind of help
I have two Formviews on the same page. I can use FindControl on the first without issue, but it always fails on the second one.
I am using the ItemTemplate for both, both default to ReadOnly, both are bound to SQLDataSources (different ones) but I cannot for the life of me work out why FindControl works for one and not the other.
I have removed a lot of the plain text from the code below.
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:SoftSaleDBConnectionString %>"
SelectCommand="SELECT * FROM [Apps] WHERE ([AppID] = #AppID)" >
<SelectParameters>
<asp:FormParameter FormField="AppID" Name="AppID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
<asp:FormView ID="FormView1" runat="server" DataKeyNames="AppID"
DataSourceID="SqlDataSource1">
<ItemTemplate>
<h1>
<asp:Label ID="AppNameLabel" runat="server" Text='<%# Bind("AppName") %>' />
<asp:Label ID="VersionLabel" runat="server" Text='<%# Bind("Version") %>' /> for
<asp:Label ID="OSLabel" runat="server" Text='<%# Bind("OS") %>' />
</h1>
<p>Text here</p>
<p><asp:TextBox ID="LicenseTextBox" runat="server"
Text='<%# Eval("License")%>'
TextMode="MultiLine" Width="800px" Rows="25" ReadOnly="True"></asp:TextBox></p>
<asp:HiddenField ID="AppLocation" runat="server" ViewStateMode="Inherit" Value='<%# Bind("AppLocation") %>'/>
</ItemTemplate>
</asp:FormView>
<p><asp:Literal ID="SizeLiteral" runat="server"></asp:Literal></p>
<asp:SqlDataSource ID="SqlDataSource4" runat="server"
ConnectionString="<%$ ConnectionStrings:SoftSaleDBConnectionString %>"
SelectCommand="SELECT * FROM [Installations] WHERE (([AppID] = #AppID) AND ([Username] = #Username))" >
<SelectParameters>
<asp:FormParameter FormField="AppID" Name="AppID" Type="Int32" />
<asp:FormParameter FormField="Username" Name="Username" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
<asp:FormView ID="DLFormView" runat="server" DataSourceID="SqlDataSource4"
DataKeyNames="AppID,Username">
<ItemTemplate>
<p> <asp:Label ID="DLAppNameLabel" runat="server" />
<br />
<br />
<asp:Label ID="NumberOfInstallations" runat="server" Text='<%# Bind("Installations") %>'></asp:Label>
<br />
<asp:HiddenField ID="TotalInstallations" runat="server" />
Number of New Installations:
<asp:DropDownList ID="NumberOfNewInstallations" runat="server">
</asp:DropDownList>
<br />
<asp:Label ID="TotalNumberOfInstallations" runat="server" Text="Label"></asp:Label>
</p>
</ItemTemplate>
</asp:FormView>
And the FindControl coding is as follows...
TextBox LicTextBox = (TextBox)FormView1.FindControl("LicenseTextBox");
HiddenField AppLocCode = (HiddenField)FormView1.FindControl("AppLocation");
Label AppNameCode = (Label)FormView1.FindControl("AppNameLabel");
These always work...
Label DLAppNameCode = (Label)DLFormView.FindControl("DLAppNameLabel");
This always returns null. I've read a million bosts about the controls not being rendered until databinding has completed, but surely if the two FOrmViews are set up the same way, the result should be the same.
Any help would be much apreciated :)
Matt :)
I'd like to plead stupidity and but also provide some background to how I've used what I've learnt from my stupidity.
My SqlDataSource for DLFormView was returning records, of course I then used slightly different values by accident and so no records were returned. I only figured this out by making the ItemTemplate section of the form view only contain unbound (basically plain text) data. As nothing displayed, this pointed towards the page using a different tempalte. When I put a test line in the EmptyDataTemplate, it displayed, confirming there was nothing returned by the SqlDataSource. Perhaps a School boy error not putting something in this template during development.
As it happens I need to use the EmptyDataTemplate anyway, I just hadn't got to this point. As only one template is rendered at a time, I have been able to use the same ID names in both templates. This means there is no need to test for which template is being used. (although empty template is used when DataItemsCount = 0, otherwise you can test for CurrentMode for the remaining templates.)
So a big fail on my part, but I hope people can learn from my mistake.
Matt :)
I am using a datapager inside a nested Listview succesfully. When only one record of data is available the next previous last and first buttons are faded as per normal. However I would like them to not appear at all.
The aspx code I have is:
<asp:ListView ID="Pictures" runat="server" DataSourceID="SqlDataSource2" >
<EmptyDataTemplate>
<span>No data was returned.</span>
</EmptyDataTemplate>
<ItemTemplate>
<span style="">
<br />
<asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("ImageUrl") %>' ToolTip='<%# Eval("ToolTip") %>'
Height="150px" />
<br />
<asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' />
<br />
<br />
</span>
</ItemTemplate>
<LayoutTemplate>
<div id="itemPlaceholderContainer" runat="server" style="">
<span runat="server" id="itemPlaceholder" />
</div>
<div style="clear: both;">
<asp:DataPager ID="DataPager1" runat="server" PageSize="1">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</div>
</LayoutTemplate>
</asp:ListView>
The code behind that I have attempted to use is:
Dim pager As DataPager = CType(e.Item.FindControl("DataPager1"), DataPager)
If (Not pager Is Nothing) Then
pager.Visible = (pager.PageSize < pager.TotalRowCount)
End If
However the pager is always nothing in the debugger i.e it can't find the control.
This may be because I have not selected the event handler correctly (I've tried several) or the method may be wrong.
Any advice gratefully received.
Try it in the listview's databound event and also call the FindControl function from the listview.
Protected Sub Pictures_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles Pictures.DataBound
Dim pager As DataPager = CType(Pictures.FindControl("DataPager1"), DataPager)
If (Not pager Is Nothing) Then
pager.Visible = (pager.PageSize < pager.TotalRowCount)
End If
End Sub