I'm trying to achieve something google isn't able to give answer. I'm trying to create an asp.net usercontrol that when I put content into it's open close tag will include it for me to be still able to acess it's content by ID from the Parent. Here is an exemple of what I want to achieve.
Usercontrol:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="ctrlGENE_CollapsiblePanel.ascx.cs"
Inherits="Controls_GenericsControls_ctrlGENE_CollapsiblePanel" %>
<asp:Panel ID="pnlHeader" CssClass="SnapPanelHeader" runat="server">
<h3>
<asp:Literal ID="litTitle" Text='<%# Text %>' runat="server" />
</h3>
<div class="SnapPanelHeader-img">
<img id="imgOpenClose" src="/images/application/close.jpg" alt="" />
</div>
</asp:Panel>
<asp:PlaceHolder runat="server" ID="pnlContent">
// **HERE I WANT TO INCLUDE THE INSIDE MARKUP**
</asp:PlaceHolder>
<act:CollapsiblePanelExtender runat="server" TargetControlID="pnlContent" ImageControlID="imgOpenClose"
ExpandControlID="imgOpenClose" CollapseControlID="imgOpenClose" CollapsedImage="/images/application/open.jpg"
ExpandedImage="/images/application/close.jpg" CollapsedSize="0" TextLabelID="litTitle">
</act:CollapsiblePanelExtender>
Parent Page that include control :
<uc:MyUserControl ID="clpTest" runat="server">
<asp:Literal ID="litText" runat="server" />
</uc:MyUserControl>
Like this I would be able in the Parent.cs file to do :
litText.Text = "Anything";
I know we can achieve something similiar with the ITemplate interface as show here : http://msdn.microsoft.com/en-us/library/36574bf6.aspx
That would look like this:
<uc:MyUserControl ID="clpTest" runat="server">
<ItemTemplate>
<asp:Literal ID="litText" runat="server" />
</ItemTemplate>
</uc:MyUserControl>
But If I do this I wouldn't be able to access the property of litText and the only way I could reach it is with a FindControl, which I want to avoid.
Anyone have a hint on this if I can reach my goal one way or another?
Thank you
Ok I fixed it here is the solution I used :
In MyUserConstrol.ascx file I have put a placeholder where I wanted innerHTML to show :
<asp:PlaceHolder runat="server" ID="plhContent" />
Then in the MyUserControl.ascx.cs file I added those attribute to the class:
[ParseChildren(false)]
[PersistChildren(true)]
And I added to the file this:
public void RegisterUpdatePanel(UpdatePanel panel)
{
MethodInfo m =
(from methods in typeof (ScriptManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
where methods.Name.Equals("System.Web.UI.IScriptManagerInternal.RegisterUpdatePanel")
select methods).First();
m.Invoke(ScriptManager.GetCurrent(Page), new object[] {panel});
}
protected override void CreateChildControls()
{
for (int i = 0; i < Controls.Count; i++)
if (Controls[i] is MyLastControl)
while (i + 2 < Controls.Count)
{
// In cas there is an updatepanel in the control we are moving
// We are registering an event to register the updatepanel
// to the scriptmanager again
SearchUpdatePanel(Controls[i + 2]);
plhContent.Controls.Add(Controls[i + 2]);
}
base.CreateChildControls();
}
private void SearchUpdatePanel(Control control)
{
if (control is UpdatePanel)
control.Unload += updPnl_Unload;
foreach (Control childcontrol in control.Controls)
SearchUpdatePanel(childcontrol);
}
protected void updPnl_Unload(object sender, EventArgs e)
{
RegisterUpdatePanel((UpdatePanel) sender);
}
Note that I named my last control in the ascx file myLastContol to know what was the control before the innerHTML injection since I don't know what I'm receiving. The the procedure basically say loop in the controls in the UserControl, when you will reach the end of UserControl, everything after is innerHTML from parent so take those and move them to the placeholder where I want them.
I hope this will help someone.
Here is some sources I used to achieve my goal :
Registering UpdatePanel
Add a public property in the user control's code behind file. If you need design time support there's more work involved, but for simple scenarios like the one you outlined it should be enough.
Then just access it in the parent page to set the value and read it in the user control and use that value to render whatever you need there.
Related
In asp net code behind I need to know the id of the parent html control of a asp control.
For example:
<div id="popuplogin" class="popuplogin">
<asp:LinkButton ID="btnRegister" OnClick="btnRegister_Click1" runat="server">LinkButton</asp:LinkButton>
Now in code behind I would like to find the id of the div control which is the parent of the linkbutton (asp control).
For example:
protected string FindParentHtmlId(Control c)
{
return etc..
}
If you want to find that div, you first need to add runat=server to be able to find it in code behind.
<div id="popuplogin" class="popuplogin" runat="server">
<asp:LinkButton ID="btnRegister" runat="server">LinkButton</asp:LinkButton>
</div>
Then you can do something like this:
protected string FindParentHtmlId(Control c)
{
var parent = c.Parent;
if (parent != null)
return parent.ID;
else
return "No parent found";
}
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.
Is there any way where we can reproduce the content of a panel.For example i have a panel which has two text box .On clicking more button i would like to have another panel below which again has two text box like the first one or add two text box into the existing panel.My end goal is to add controls as the user clicks on more button and get data from those controls .This is the controls inside the panel that i would like to reproduce
any possible way where i can add the controls as shown in the layout through server side ?Please help!
There are plenty ways to solve this. You could add proper DOM elements by yourself using plain JavaScript or jQuery, or use some JS MV* frameworks, like KnockoutJS (example: http://knockoutjs.com/examples/contactsEditor.html) or AngularJS.
you can obviously add dynamic controls from code behind on button click event of 'more button'.
Click Here for more references:
If you want to achieve this on client side using jQuery, then 'closest()' (to find the source element/row to be repeated nearby to the add/remove button etc., especially if it is in a tabular/grid format) in conjunction with 'clone()' function, (to make a copy of the source element/row) and then you can paste the clone inside the target container.
The following link might help you achieve what you want:
jQuery Clone table row
But doing this in Asp.Net WebForms should be much straight forward.
Also, please be noted that, it would always be much helpful to get a quicker answer by specifying more details(eg., MVC, WebForms etc. in the description, what trials you did to find/fix the problem) and that help save other's time as well. For more info: https://stackoverflow.com/questions/how-to-ask
try this
your aspx page add
<asp:TextBox runat="server" ID="TextBox1" />
<asp:TextBox runat="server" ID="TextBox2" />
<asp:Button Text="Add" ID="btnAdd" OnClick="btnAdd_Click" runat="server" />
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("str1") %>' />
<asp:TextBox runat="server" ID="txt2" Text='<%# Eval("str2") %>' /><br />
</ItemTemplate>
</asp:Repeater>
and in code behind
protected void btnAdd_Click(object sender, EventArgs e)
{
List<temp> lst = GetItemFromRpt();
lst.Add(new temp
{
str1=TextBox1.Text,
str2 = TextBox2.Text
});
rpt.DataSource = lst;
rpt.DataBind();
}
private List<temp> GetItemFromRpt()
{
List<temp> lst = new List<temp>();
for (int i = 0; i < rpt.Items.Count; i++)
{
temp obj = new temp();
obj.str1 = ((TextBox)rpt.Items[i].FindControl("txt1")).Text;
obj.str2 = ((TextBox)rpt.Items[i].FindControl("txt2")).Text;
lst.Add(obj);
}
return lst;
}
public class temp // instead of temp you can use whatever your entity class you need
{
public string str1 { get; set; }
public string str2 { get; set; }
}
I have a list of files (stored in a database) that I would like the user to be able to upload in asynchronous callbacks.
I have got as far as displaying AJAX Control Toolkit's AsyncFileUpload controls next to the name of each file I'm expecting:
<asp:Repeater ID="SourceTables" runat="server">
<ItemTemplate>
<tr>
<td>
<%#DataBinder.Eval(Container.DataItem, "LongName")%>
</td>
<td>
<ajax:AsyncFileUpload runat="server" ClientIDMode="AutoID" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
All of these async upload controls will end up calling the same method in code behind, which is fine, but when I come to save the file I need some way to identify which control is causing the postback (i.e. which of the several files has just been uploaded). However, I have been unable to set the ID dynamically inside the repeater (I believe it is only possible from code behind).
Clearly this doesn't work:
<ajax:AsyncFileUpload ID=<%#DataBinder.Eval(Container.DataItem, "ShortName")%> runat="server" ClientIDMode="AutoID" />
Is there another way I can set the ID of each of the upload controls dynamically inside the repeater (or otherwise) or another approach I can take?
You can add controls dynamically in "ItemDatabound" event of the repeater.
How are you handling the postback events?
If you are using the UploadedComplete event of the AsyncFileUpload control, you get the uploaded file through the AsyncFileUploadEventArgs object.
You could also cast sender to your AsyncFileUpload control and then get the file through the PostedFile property.
protected void AsyncFileUpload1_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
{
string savePath = MapPath("~/Uploads/" + Path.GetFileName(e.filename));
}
Something like this
<ajax:AsyncFileUpload runat="server" id="afuMyUpload" ClientIDMode="AutoID" OnClientUploadComplete="MyFunction" />
foreach (Control c in SourceTables.Items)
{
var myUpload = c.FindControl("afuMyUpload") as AsyncFileUpload;
//Do stuff with your control
}
You can't bind the ID property of controls. You will need to create the control in code behind and add it to the repeater.
Example:
protected void GridDataBind(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow) {
IEnumerable list = PremiumUnitFees.PremiumAmenities.ObtainFeesForProject(IntranetUser.Current.ProjectId);
foreach (PremiumUnitFees.PremiumAmenities feature in list) {
e.Row.Cells(3).Controls.Add(new CheckBox {
ID = feature.Id.ToString(),
Text = feature.NickName,
Checked = PremiumUnitFees.PremiumUnitView.IsUnitPremium(feature.Id, Convert.ToInt64(DataBinder.Eval(e.Row.DataItem, "Id")))
});
}
}
}
I have a master page file that contains a 2 menu's in a 2 panel controls.
I also use a control to check if user is logged in and get the type of user.
Deppending on the type I want to show / hide the panel. The control itself is not referenced in the master page but dynamically through the CMS System.
I want to use findcontrol in the user control to find the panel control in the master page. I have tried different methods but all come back with null.
The content placeholder in the master page is
asp:Content runat="server" ContentPlaceHolderID="PHMainBlock"
and the control is called
asp:Panel ID="NormalUser" runat="server"
I have tried using the code....
Panel ph = (Panel)Page.Master.FindControl("NormalUser");
ph.Visible = false;
but brings back null, any help?
thanks..
You could create a public property in you Master Page i.e
public bool ShowPanel
{
set
{
NormalUser.Visible = value;
}
}
And call it like this
if (Page.Master is NameOfMasterPage)
{
((NameOfMasterPage)Page.Master).ShowPanel = false;
}
Because the Panel control is inside a ContentPlaceHolder control, you must first get a reference to the ContentPlaceHolder and then use its FindControl method to locate the TextBox control.
ContentPlaceHolder mpContentPlaceHolder;
Panel pn;
mpContentPlaceHolder = (ContentPlaceHolder)Master.FindControl("PHMainBlock");
if(mpContentPlaceHolder != null)
{
pn = (Panel) mpContentPlaceHolder.FindControl("NormalUser");
pn.Visible = false;
}
http://msdn.microsoft.com/en-us/library/xxwa0ff0.aspx
Here's how I do something similar and it works fine:
if (Page.Master != null)
{
var tempPanel = Page.Master.FindControl("MessagePanel") as UpdatePanel;
if (tempPanel != null)
tempPanel.Visible = true;
var temp = Page.Master.FindControl("MessageForUser") as MessageToUser;
if (temp != null)
temp.PostWarningMessage(message, msgInterval);
}
However, I have "MessagePanel" and "MessageForUser" as controls right above the ContentPlaceHolder. Here's my markup:
<asp:UpdatePanel runat="server" Visible="true" ID="MessagePanel" >
<ContentTemplate>
<msg:MainMessage ID="MessageForUser" runat="server" Visible="true" />
<br />
</ContentTemplate>
</asp:UpdatePanel>
<asp:ContentPlaceHolder ID="cphContent" runat="server" Visible="true">
</asp:ContentPlaceHolder>
If you have your Panel inside of a tag, then you should be able to reference the panel without needing Page.Master.FindControl.
One way would be to solve this problem with javascript (jquery):
$('.NormalUser').hide();
http://api.jquery.com/hide/