The Controls collection cannot be modified because the control contains code blocks - c#

This is a bit different to all the other questions as they all seem to refer to the head content specifically. With this one, I have a user control with the following placeholder:
<asp:PlaceHolder runat="server" ID="DiscussIncludes">
<script>
var OnLastPage = <asp:Literal runat="server" ID="OnLastPageJS" />;
var AJAXWait = false;
var MinChars = <%=Settings.MinimumCommentChars%>;
var AJAXURL = "<%=ResolveClientUrl("~/Handlers/DiscussAjaxHandler.ashx")%>";
var CurrUsername = "<%=ThisUser.Username %>";
var GravHash = "<asp:Literal runat="server" ID="GravJSRef" />";
var RelURL = "<%=ResolveClientUrl("~/users/")%>";
var Anch = "<%=Anchor.ToString()%>";
var MyRep = "<%=MyRepString%>";
var CurrReportID = 0;
var LastPageURL = "<asp:Literal runat="server" ID="JSLastPageURL" />";
var AllowedChars = <%=Settings.MaxCommentChars %>;
</script>
<script src="<%=CommonFunctions.AllocateStaticPath("/js/Discuss.js?v=" + Settings.JSVersionID)%>"></script>
<script src="<%=CommonFunctions.AllocateStaticPath("/js/BlockUI.js?v=" + Settings.JSVersionID)%>"></script>
</asp:PlaceHolder>
In the code behind I have:
ContentPlaceHolder FooterControl = (ContentPlaceHolder)Page.Master.FindControl("JavascriptIncludes");
FooterControl.Controls.Add(DiscussIncludes);
This throws the error:
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
On the FooterControl.Controls.Add(DiscussIncludes); line. I've tried changing all the <%= to <%# within the placeholder but no luck.
One point to note is this control works fine on all my other pages. Any ideas what would be causing this?

Nothing in this control is causing the problem -- if it happens when you add the control to a particular environment and only that environment the that points at the issue. What is going on on the complaining page?

I tried the following on my system and it seems to be working...
<asp:PlaceHolder runat="server" ID="DiscussIncludes">
<script type="text/javascript">
var path = <%=Common.path%>;
</script>
<script type="text/javascript" src='<%=Common.GetScriptPath("jquery-1.4.1-vsdoc.js")%>'></script>
<asp:PlaceHolder runat="server" ID="JsIncludes">
</asp:PlaceHolder>
</asp:PlaceHolder>
on code behind..
LiteralControl include = new LiteralControl(string.Format("<script src='{0}'></script>", Common.GetScriptPath("jquery-1.4.1.min.js")));
JsIncludes.Controls.Add(include);
I get the exception if i try to add the control to DiscussIncludes. However if add the control to JsIncludes it works. JsIncludes control is a child placeholder of DiscussIncludes.

Related

MaintainScrollPositionOnPostback is not working?

I have a page with two drop down lists (ddlA and ddlB)
Once the user selects an item from ddlA, it will populate items in ddlB
I have auto post-back turned on for ddlA.
and since I wanted to maintain the scroll position, i turned on the MaintainScrollPositionOnPostBack to true like this in the page load method. :
this.MaintainScrollPositionOnPostBack = true;
But this doesn't seem to fix the issue.
Is there a workaround to fix the problem.?
-- UPDATE --
I added this js code to the page and now the problem is that the autopost back is never happening..
<script type="text/javascript">
var xPos, yPos;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginRequestHandler);
prm.add_endRequest(EndRequestHandler);
function BeginRequestHandler(sender, args) {
xPos = $get('scrollDiv').scrollLeft;
yPos = $get('scrollDiv').scrollTop;
}
function EndRequestHandler(sender, args) {
$get('scrollDiv').scrollLeft = xPos;
$get('scrollDiv').scrollTop = yPos;
}
</script>
Am i adding the js code incorrectly? I found it here
Try to add this to the Page directive in your ASPX file and test it that route.
<%# Page Title="" Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" MaintainScrollPositionOnPostback="true" Inherits="_Default" %>
I couldn't get MaintainScrollPositionOnPostback to work for me no matter what I tried. Based on this answer (https://stackoverflow.com/a/27505983) and a comment underneath it, I tried the following code which worked for me. This will only work if you have an ASP.NET ScriptManager (i.e. MicrosoftAjax.js) on your page. You also need JQuery added to your page. Add the below code to your .aspx file somewhere underneath asp:ScriptManager tag.
<asp:HiddenField runat="server" ID="hfPosition" Value="" />
<script type="text/javascript">
$(function () {
var positionField = $("#<%=hfPosition.ClientID%>");
window.onscroll = function () {
var position = $(window).scrollTop();
positionField.val(position);
};
});
function pageLoad() {
var positionField = $("#<%=hfPosition.ClientID%>");
var position = parseInt(positionField.val());
if (!isNaN(position)) {
$(window).scrollTop(position);
}
};
</script>
Basically we are holding the scroll position inside the value of a hidden field called hfPosition. Whenever the page is scrolled, the value will be updated. Then when a postback happens pageLoad() will automatically be called and will get the value of hfPosition and scroll to that value.
Including the ScriptManager and JQuery, my final code snippet looked something like this:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<script src="../Scripts/jquery-3.3.1.min.js" type="text/javascript"></script>
<asp:HiddenField runat="server" ID="hfPosition" Value="" />
<script type="text/javascript">
$(function () {
var positionField = $("#<%=hfPosition.ClientID%>");
window.onscroll = function () {
var position = $(window).scrollTop();
positionField.val(position);
};
});
function pageLoad() {
var positionField = $("#<%=hfPosition.ClientID%>");
var position = parseInt(positionField.val());
if (!isNaN(position)) {
$(window).scrollTop(position);
}
};
</script>/>

Forward-Slash missing from string in Sitecore Sublayout

I have a function in the C# code behind of a Sitecore sublayout that returns a string that looks like this:
public string getProductTitle()
{
Item productItem = itemHelper.GetItemByPath(currentItemPath);
Sitecore.Data.Fields.ImageField imgField = ((Sitecore.Data.Fields.ImageField)productItem.Fields["Logo"]);
if (imgField.Value != "")
{
return "<sc:Image CssClass=\"product-image ng-scope\" Field=\"Logo\" runat=\"server\" />";
}
string productTitle = "";
productTitle = productItem["Produkt Titel"];
return "<div class=\"product-name ng-binding ng-scopen\" ng-if=\"!currentProduct.imageNameHome\">" + productTitle + "</div>";
}
And in the ascx I call this fuction:
<%= getProductTitle() %>
The problem is that in the end this is what I'm getting in HTML at runtime:
"<sc:Image CssClass=\"product-image ng-scope\" Field=\"Logo\" runat=\"server\" >";
The / at the end is missing, which breaks the whole line and no image is shown. The
I also tried this:
string a = WebUtility.HtmlEncode("<sc:Image CssClass=\"product-image ng-scopen\" Field=\"Logo\" runat=\"server\" />");
return WebUtility.HtmlDecode(a);
and this:
return #"<sc:Image CssClass=""product-image ng-scopen"" Field=""Logo"" runat=""server"" />";
With the same result.
Am I missing something here? How can I fix this?
I cannot see this working due to the ASP.NET page life cycle.
Sitecore controls are like normal user controls and they run on the server side - returning them as a string will be too late in the page lifecycle for them to render.
I would place the <sc:Image /> control in the ascx page or use a FieldRenderer object to get the HTML from Sitecore
Sitecore.Web.UI.WebControls.FieldRenderer.Render(myItem, "MyFieldName", "disable-web-editing=true");
You can then use logic to show or hide the Image Field and title control based on you requirements. This assumes you are using the Sitecore Context Item.
Replace the <%= getProductTitle() %> with
<sc:Image runat="server" ID="imgLogo" Field="Logo" />
<asp:Placeholder runat="server" ID="phTitle">
<div class=\"product-name ng-binding ng-scopen\" ng-if=\"!currentProduct.imageNameHome><sc:Text runat="server" ID="title" Field="Produkt Titel"/></div>
</asp:Placeholder>
Then in the code behind Page Load method
var currentItem = Sitecore.Context.Item;
if(string.IsNullOrEmpty(currentItem["Logo"])
{
imgLogo.Visible=False;
}
if(string.IsNullOrEmpty(currentItem["Produkt Titel"])
{
phTitle.Visible=False;
}
More information here:
http://gettingtoknowsitecore.blogspot.co.uk/2010/01/displaying-field-values-using-server.html
Since you have two alternate ways you wish to present your information, I would consider moving your controls and HTML to your markup file (ASCX) and then wrapping the segments in asp:placeholder controls.
<asp:placeholder id="imageTitle" runat="server" Visible="false">
<sc:Image CssClass="product-image ng-scope" Field="Logo" runat="server" />
</asp:placeholder>
<asp:placeholder id="textTitle" runat="server>
<div class="product-name ng-binding ng-scopen" ng-if="!currentProduct.imageNameHome">
<asp:Literal id="productTitleLiteral" runat="server" />
</div>;
</asp:placeholder>
You can then toggle the visibility of the placeholder in your code behind during page load.
public void Page_Load{
Item productItem = itemHelper.GetItemByPath(currentItemPath);
Sitecore.Data.Fields.ImageField imgField = ((Sitecore.Data.Fields.ImageField)productItem.Fields["Logo"]);
if (imgField.Value != "")
{
this.imageTitle.Visible = true;
this.textTitle.Visible = false;
}
else {
this.imageTitle.Visible = false;
this.textTitle.Visible = true;
this.productTitleLiteral.Text = productItem["Produkt Titel"];
}
}
This will allow you to ensure proper encapsulation of business logic versus presentation markup, and will work better with the .NET lifecycle.

How to disable a control inside a User Control

I thought this would be a simple thing to accomplish but am having some issue. My initial asp.net markup for the server control looks like this:
<ucTextArea:UserControlTextArea ID="taRemarks" runat="server" />
However, in the code behind, I have a conditional statement that checks for user rights in order to enable this text field or not, something like this:
if (CurrentUser.AccountTypeID == 4 || CurrentUser.AccountTypeID == 6)
taRemarks.Attributes.Add("enabled", "");
else
taRemarks.Attributes["disabled"] = "true";
Above are two ways I have tried to accomplish this, but haven't worked when rendered in the browser. How can I disable this server control?
Edit: The UserControlTextArea.ascx is defined below:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControlTextArea.ascx.cs" Inherits="stuff....UserControlTextArea" %>
<script type="text/jscript" language="javascript">
$(document).ready(function () {
var counterLabel = $('#<%=lblCounter.ClientID %>');
var textArea = $('#<%=tbTextArea.ClientID %>');
var maxNumber = parseInt('<%=txtMaxCharacters.Value%>');
FieldCounter(textArea, counterLabel, maxNumber);
$(textArea).keyup(function () {
CheckFieldLength($(textArea), maxNumber);
FieldCounter(textArea, $(counterLabel), maxNumber);
});
});
</script>
<div id="OuterContainer" runat="server">
<asp:TextBox ID="tbTextArea" runat="server" TextMode="MultiLine" Width="100%"></asp:TextBox>
<span class="fieldLengthCounter">
characters left:
<asp:Label ID="lblCounter" runat="server"></asp:Label>
</span>
<input type="hidden" runat="server" id="txtMaxCharacters" />
</div>
Your question is unclear, but definitely its a UserControl and not a ASP.Net Textbox. So you can disable the textbox inside your UC like this:-
Approach 1 (Preferred):
Add a public property in your UserControl code-behind:-
public bool DisableMyTextbox
{
set { tbTextArea.Enabled = value; }
}
Then you can simply use this property to disable your textbox in Webform:-
UserControlTextArea.DisableMyTextbox = false; //or true to enable back.
Approach 2:
Find your textbox in UserControl class and then disable it:-
TextBox txt1 = (TextBox)SimpleUserControl1.FindControl("tbTextArea");
txt1.Enabled = false;

SAP UI5 with ASP: Repeater Control

Does anyone know how to use an sap ui5 control with the asp:repeater control. Everytime I try to put a button, it only shows up in the first iteration of the repeater. And not in the rest of the iterations
<asp:Repeater ID="NewsFeedID" runat="server" >
<ItemTemplate>
<script type="text/javascript">
var buttonlink = CommentsPage + "?news=" + '<%# Eval("NewsFeedID") %>';
var AddComment = new sap.ui.commons.Button({
text: "Add Comment",
icon: AddCommentIcon,
lite: true,
press: function () { window.location = buttonlink; }
}).placeAt("Comments");
</script>
<div id="Comments"></div>
</td>
</tr>
When I use this code it only shows up for the first iteration of the asp:repeater but I want it to show up for all iterations. Does it have something to do with the div id=Comments? Need help please
Your Repeater creates multiple <div> elements with the same id, which causes conflicts.
One way to fix the problem is to add a runat="server" attribute to the <div>, making it a server-side control so that ASP.NET generates a unique ID for each instance:
<div runat="server" id="Comments"></div>
Then pass the dynamically generated ID to the placeAt function:
}).placeAt("<%# Container.FindControl("Comments").ClientID %>");
You can rename every instance with the index of repeater item:
<script type="text/javascript">
var buttonlink = CommentsPage + "?news=" + '<%# Eval("NewsFeedID") %>';
var AddComment = new sap.ui.commons.Button({
text: "Add Comment",
icon: AddCommentIcon,
lite: true,
press: function () { window.location = buttonlink; }
}).placeAt("<%# "Comments"+ Container.ItemIndex+1 %>");
</script>
<div id="<%# "Comments"+ Container.ItemIndex+1 %>"></div>

images are not being displayed

I have done the following jquery function which is supposed to change dynamically images. The problem is that it is doing nothing as if there is no jquery function. The jquery function is being totally ignored without even enter in the function.
The coding I used is the one below;
<asp:Content ID="Content1" ContentPlaceHolderID="stylesPlaceHolder" runat="server">
<script type="text/javascript">
var index = 0;
var images = [
'child.jpg',
'girl.gif',
'sponsor.jpg'
];
$('Image1').attr('src', 'Resources/ChildrenImages/' + images[0]);
setInterval(change_image, 5000);
$(document).ready(function() {
index++;
if (index >= images.length) index = 0;
$('Image1').attr('src', 'Resources/ChildrenImages/' + images[index]);
});
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="contentPlaceHolder" runat="server">
<div>
<asp:Image ID="Image1" runat="server" Height="198px" Width="225px"/>
</div>
</asp:Content>
Any suggestions to what the problem could be?
The problem is that you're probably not selecting anything:
$('Image1')
should be
$('#Image1')
Please note also that there's a difference between the ID that you set and the rendered one (which is ClientID in ASP.net), so you should either use:
$('img[id$="Image1"]') //Select an image whose ID ends with 'Image1'
Or reference the ClientID property in your script.
Set the ClientIDMode property of the Image to Static, and as per the other answer the JQuery Identifier should start with a #, #Image1.

Categories

Resources