Using Panel or PlaceHolder - asp.net

What is the difference between <asp:Panel > and <asp:PlaceHolder > in ASP.NET?
When should you use one over the other?

A panel expands to a span (or a div), with it's content within it. A placeholder is just that, a placeholder that's replaced by whatever you put in it.

The Placeholder does not render any tags for itself, so it is great for grouping content without the overhead of outer HTML tags.
The Panel does have outer HTML tags but does have some cool extra properties.
BackImageUrl: Gets/Sets the
background image's URL for the panel
HorizontalAlign: Gets/Sets the
horizontal alignment of the parent's
contents
Wrap: Gets/Sets whether the
panel's content wraps
There is a good article at startvbnet here.

PlaceHolder control
Use the PlaceHolder control as a container to store server controls that are dynamically added to the Web page. The PlaceHolder control does not produce any visible output and is used only as a container for other controls on the Web page. You can use the Control.Controls collection to add, insert, or remove a control in the PlaceHolder control.
Panel control
The Panel control is a container for other controls. It is especially useful when you want to generate controls programmatically, hide/show a group of controls, or localize a group of controls.
The Direction property is useful for localizing a Panel control's content to display text for languages that are written from right to left, such as Arabic or Hebrew.
The Panel control provides several properties that allow you to customize the behavior and display of its contents. Use the BackImageUrl property to display a custom image for the Panel control. Use the ScrollBars property to specify scroll bars for the control.
Small differences when rendering HTML: a PlaceHolder control will render nothing, but Panel control will render as a <div>.
More information at ASP.NET Forums

I weird bug* in visual studio 2010, if you put controls inside a Placeholder it does not render them in design view mode.
This is especially true for Hidenfields and Empty labels.
I would love to use placeholders instead of panels but I hate the fact I cant put other controls inside placeholders at design time in the GUI.

As mentioned in other answers, the Panel generates a <div> in HTML, while the PlaceHolder does not. But there are a lot more reasons why you could choose either one.
Why a PlaceHolder?
Since it generates no tag of it's own you can use it safely inside other element that cannot contain a <div>, for example:
<table>
<tr>
<td>Row 1</td>
</tr>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</table>
You can also use a PlaceHolder to control the Visibility of a group of Controls without wrapping it in a <div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server" Visible="false">
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</asp:PlaceHolder>
Why a Panel
It generates it's own <div> and can also be used to wrap a group of Contols. But a Panel has a lot more properties that can be useful to format it's content:
<asp:Panel ID="Panel1" runat="server" Font-Bold="true"
BackColor="Green" ForeColor="Red" Width="200"
Height="200" BorderColor="Black" BorderStyle="Dotted">
Red text on a green background with a black dotted border.
</asp:Panel>
But the most useful feature is the DefaultButton property. When the ID matches a Button in the Panel it will trigger a Form Post with Validation when enter is pressed inside a TextBox. Now a user can submit the Form without pressing the Button.
<asp:Panel ID="Panel1" runat="server" DefaultButton="Button1">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ErrorMessage="Input is required" ValidationGroup="myValGroup"
Display="Dynamic" ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" ValidationGroup="myValGroup" />
</asp:Panel>
Try the above snippet by pressing enter inside TextBox1

Related

ASP.NET closing tag

When I use autocompletion in VisualStudio 2010 within my .aspx application, there are different default completions at closing control tags:
<asp:CheckBox />
<asp:Label></asp:Label>
Is there a explaination for this behaviour?
<asp:CheckBox></asp:CheckBox>
<asp:Label />
Wouldn't be invalid.
This is because ASP.NET's Label control is decorated with the ParseChildrenAttribute, with ParseChildren(false) while CheckBox isn't.
You can support the same behavior whith your custom controls, for example, with the following code, Visual Studio will behave like Label if you use MyControl in the web form editor:
[ParseChildren(false)]
public class MyControl : WebControl
{
...
}
The label closing is like that
<asp:Label runat="server"></asp:Label>
because usually we type something between
<asp:Label runat="server" ID="lblOne">better start programming now</asp:Label>
that is not the case for checkbox, that we type inside of it
<asp:CheckBox runat="server" Text="enable" ID="cbOne" />
We have on both elements the Text field, why on the one we prefer to write out side... Look at this example, on Label, or On other similar controls the text that we may have to write may include characters that are not allowed inside the Text Property, maybe a complex css style or what ever... The check box from the other side is only include a small text (yes, not, something like that)
<asp:Label ID="lblLabel" runat="server">
This is a <b>"label"</b>
<br />And one more line
</asp:Label>
and more example that compiles
<asp:Label ID="lblLabel" runat="server">
This is a <b>"label"</b>
<br />And one more line
<asp:Literal runat="server" ID="ltrOneMore">One more Control Inside</asp:Literal>
</asp:Label>
---but this is not compile--
<asp:Label ID="lblLabel2" runat="server"
Text="This is a <b>"label"</b>
<br /> and one more line"
/>
At the final end is a decision that the makes make - maybe we need to ask them for the real real reason.
Now this is also not compile
<asp:CheckBox runat="server" ID="cbMyChbx">one<asp:CheckBox>
check box when is render on page is use two controls, one input and one label, so they maybe need to help user to understand that the text is not going on the input control.
<asp:CheckBox />
Because the element has no content, you can close the tag with /> instead of using a separate closing tag
<asp:Label></asp:Label> or <asp:Label />
Displays static text on a Web Forms page and allows you to manipulate it programmatically.
Learn more about it Web Server Control
All the answers above are valid, but something additional. All the asp controls are eventually rendered as HTML controls and that also defines how the asp controls behave. For e.g. it is not necessary that text in a label is always set as
<asp:Label runat="server" ID="lblOne">better start programming now</asp:Label>
it can be also done as follows
<asp:Label runat="server" ID="lblOne" Text="better start programming"></asp:Label>
now both are correct format, so it is not valid to say that any control which needs content will have a separate closing tag. It also depends on how it rendered in HTML. for e.g by default asp Label is rendered as a span and doesnt conform to XHTML standards. Hope this makes it clear, always think of how it will be rendered and ASP tries to adhere to what eventually will be rendered.
cheers

Unable to edit text value in Sitecore

When hovered over the text 'Bedroom', the blue dotted box appears over it, but clicking on it, does not place the cursor, as if it is read-only.
However, I am able to edit the rendered images. And also the text 'Water View Loft' coming from another repeater, without issues.
ascx:
<asp:Repeater ID="rpPhotos" runat="server" ItemType="Sitecore.Data.Items.Item">
<ItemTemplate>
<div class="item">
<p>
<sc:Text runat="server" Field="Title" Item="<%#Container.DataItem %>"/>
</p>
<sc:Image runat="server" Field="Image" Item="<%#Container.DataItem %>" />
</div>
</ItemTemplate>
</asp:Repeater>
The fields Title & Image are from a template called Base Content. I have used this template to render other repeater in the same user control & there I can edit the text & images.
Why is this happening?
Try to remove the <p> tag, and see if the field gets editable. The Page Editor gets broken on nested <p> tags, and perhaps it happens also in your case.
Try to set the DisableWebEditing="false".

Nested UpdatePanel causes parent to postback?

I'm under the impression that a control in a nested UpdatePanel will cause the top level UpdatePanel to refresh (thus refreshing both UpdatePanels) because any events on that control act as an "implicit" trigger. Is that correct?
I've been trying to wire something like this up-
UserControl
Parent UpdatePanel
"Show" button
ASP:Panel
Dynamically added UserControls, each with UpdatePanels
When the Show button is clicked, the ASP:Panel becomes visible and starts adding UserControls to itself dynamically, based on some back-end logic.
Each of the dynamically added controls (henceforth: UserControls) have their own Atlas-enabled buttons and links, so they have UpdatePanels too. Currently when I click on a link in one of the UserControls, the entire contents of the ASP:Panel disappear, as if it's being re-rendered. All of my dynamically-added controls disappear, and none of their click events are caught in the debugger.
I'm assuming what's happening here is that controls that reside in nested update panels are causing the parent UpdatePanel to post back because they're firing "implicit" triggers. Is there a way for my UserControls to operate autonomously and not mess with the ASP:Panel that contains them?
If not, what strategy should I be pursuing here? If I have to re-render the entire ASP:Panel every time an event happens on one of the (possibly many) UserControls, that means I'll have to recreate the UserControls, which take a bit of effort to create. I'll also have to preserve some kind of view state to recreate them. I'm somewhat new to ASP.NET and that sounds intimidating. I'd rather never refresh the top leve UserControl and ASP:Panel if I can avoid it, and let each of the dynamically-added UserControls fire and handle their own events asynchronously.
EDIT: Instead of adding the controls dynamically, I added them to the markup(not a bad solution). So got rid of the controls disappearing problem, because now the controls are not added dynamically but instead exist in the markup. But still the parent UpdatePanel posting is a big performance hit, because all the UserControls are getting posted instead of one. How do I make only one UserControl postback? Also, I would like to know how to get rid of the problem of controls disappearing if added dynamically?
First off, keep in mind: UpdatePanels do not alter the lifecycle of a page.
All of the Control Tree (including the UpdatePanels) must be reconstructed just as with a Normal Postback Life-cycle.1 2 The UpdatePanels ensure that only a portion of the rendered (HTML) view is returned. Removing all UpdatePanels should result in the same behavior, except with a full postback. For instance, only the HTML representing a nested UpdatePanel (presumably because data changed) might be sent back in the XHR response.
To get "true" AJAX consider Page Methods. Alternatively, DevExpress (and perhaps Telerik and others?) offer their own form of "Callback Panels", which are similar to UpdatePanels, but can bypass parts of the life-cycle (and, as a result often do not support the ViewState model entirely or may introduce their own quirks).
While not understanding the above is the most likely reason for the controls "disappearing", here is my rule: Do Not Let [Nested] UpdatePanels Work "Automatically".
Edge cases with dynamic controls and nested UpdatePanels will be encountered. There might be a nice way to handle this, but I have failed on multiple different attempts.
Instead, for every update panel, run with:
UpdateMode="Conditional"
ChildrenAsTriggers="False"
With the "Conditional" UpdateMode, make sure to manually specify the Trigger control or call panel.Update() (although this hard-wires the Control) as required. Depending on needs ChildrenAsTriggers="True" might work as well. The big thing is that UpdateMode is not "Always" which is the default.
After switching to this approach, I have no problem -- well, almost none -- with nested UpdatePanels.
Happy coding!
1 If the page doesn't render correctly where Partial Rendering (in the ScriptManager) is disabled (e.g. all requests are full postbacks) then there is no reason to expect/believe it will work correctly with UpdatePanels.
2 There are times when it's warranted to "cheat" expensive recomputations in the control tree for controls that will not be re-rendered. However, I would consider these advanced cases that should only be done when performance analysis indicates there is a specific need.
I had a similar issue with a heavy ajax Gridview control, and a HTML page with multiple UpdatePanels, some nested, some not.
It took me over 3 weeks of trial and error, reading, testing, debugging and prototyping to finally resolve all the post backs and partial postbacks.
However I did notice a pattern, which worked for me.
Like the #user above's response, make sure your UpdatePanels are set Conditional and only specificy asp:PostBackTrigger on the final or decisive control that you want the page to do a full postback on. I always use asp:AsyncPostBackTrigger where ever possible.
So for example, if you're using UpdatePanels inside a GridView and you want a popup inside a cell of the gridview's row, then you need to use a nested UpdatePanel.
ie
<asp:TemplateField HeaderText="Actions & Communications">
<ItemTemplate>
<asp:UpdatePanel ID="upAction1" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnActionOK" />
</Triggers>
<ContentTemplate>
...
...
<ajaxToolkit:ModalPopupExtender ID="ajaxMPE" runat="server"
BackgroundCssClass="modalBackground"
PopupControlID="upAction2"
TargetControlID="btnADDaction">
</ajaxToolkit:ModalPopupExtender>
<asp:UpdatePanel ID="upAction2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="pnlACTION" runat="server" CssClass="pnlACTION">
<div id="divHDR">
<asp:Label ID="lblActionHdr" runat="server">** header **</asp:Label>
</div>
<div id="divBOD">
<table style="width: 98%; text-align:left">
<tr>
<td colspan="2">
Please enter action item:<br />
<asp:TextBox ID="txtAction" runat="server" ValidationGroup="vgAction" TextMode="MultiLine" Rows="3" Width="98%"></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvAction" runat="server" ControlToValidate="txtAction" ValidationGroup="vgAction"
ErrorMessage="* Required" SetFocusOnError="True"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td colspan="2">
Select staff assigned to this task:<br />
<asp:DropDownList ID="ddlActionStaff" runat="server" AppendDataBoundItems="true" ValidationGroup="vgAction" />
<asp:RequiredFieldValidator ID="rfvStaff" runat="server" ControlToValidate="ddlActionStaff" InitialValue="0" ValidationGroup="vgAction"
ErrorMessage="* Required" SetFocusOnError="True" Width="98%"></asp:RequiredFieldValidator></td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<asp:Button ID="btnActionOK" runat="server" Text="OK" OnClick="btnActionOK_Click" ValidationGroup="vgAction" CausesValidation="false" />
<asp:Button ID="btnActionCANCEL" runat="server" Text="CANCEL" OnClick="btnActionCANCEL_Click" ValidationGroup="vgAction" CausesValidation="false" />
</td>
</tr>
</table>
</div>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
<asp:SqlDataSource ID="sdsTETactions" runat="server" ConnectionString="<%$ ConnectionStrings:ATCNTV1ConnectionString %>"
...
...
</asp:SqlDataSource>
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
Notice a few things here:
The ModalPopupExtender does not refer to the Ok and Cancel buttons. This is because I want them to trigger a partial postback to the server (code-behind)
The nested UpdatePanel (upAction2) is purely to force a partial postback on that panel only (pnlAction)! Therefore this forces the data validation triggers to work and keep the panel open if the user does not provide data in the requiredfield validators
The main UpdatePanel (upAction1) controls the entire lot and keeps all postbacks held within that panel only and NOT affecting the gridview (not shown entirely).
There is a great article here, which explains it better.
I hope this helps someone

Update Panel - Textbox TextChanged Event is interfering with the DropDown SelectedIndexChanged event

Basics:
I have a text box (txtDepositAmount) that people can
enter a deposit amount into and a
drop down (ddlSelectedTerm) that sets the terms.
Through these two values I calculate
the APY (lblCurrentApy).
Rules:
If only one of the values is selected I still want to do an update on the current APY label and clear it.
If either value changes I want to update the current APY and recalculate.
The problem:
As soon as I click away from the textbox and onto the drop down to select my term the drop down flashes and closes because the textbox TextChanged event was just fired.
I have to click on the drop down a second time to be able to select anything!
Do I need to change what event I'm looking at or do I need to move some of the controls outside of the UpdatePanel? Can this only happen if some of the business rules change? Should I just give up and go to javascript?
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table width="100%">
<tr>
<td align="left" style="width: 10%" class="LineAlign">
</td>
<td align="left" style="width: 40%" class="LineAlign">
<asp:Label ID="lblDollarSymbol" runat="server" Text="$"/>
<asp:TextBox ID="txtDepositAmount" runat="server"
AutoPostBack="true" TabIndex="1" MaxLength="14"
ontextchanged="txtDepositAmount_TextChanged"/>
</td>
<td align="left" style="width: 30%" class="LineAlign">
<asp:DropDownList ID="ddlSelectedTerm" runat="server"
AutoPostBack="true" TabIndex="2"
onselectedindexchanged="ddlSelectedTerm_SelectedIndexChanged">
</asp:DropDownList>
</td>
<td align="center" style="width: 20%">
<asp:Label ID="lblCurrentApy" runat="server"/>
<asp:Label ID="lblPercentSymbol" runat="server" Text="%"/>
</td>
</tr>
</table>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlSelectedTerm" />
<asp:AsyncPostBackTrigger ControlID="txtDepositAmount" />
</Triggers>
</asp:UpdatePanel>
autopostback="true" on your textbox is causing this, since both controls are reloaded after they leave the textbox. I doubt there is a way to avoid this as long as they are in the same UpdatePanel.
Maybe you could set focus to the dropdown list after the textbox-initiated postback, or you could probably make this work by putting the controls in separate UpdatePanels. But really it seems the wrong way to go about it. I would use javascript (and ajax if the logic is complicated) to update the APY. Or just add a "calculate" button...
(Edit)
Here's a slightly ugly hack to avoid ajax, three update panels and still be able to do your logic server side. I do not approve of this method but it is quick and dirty.
Put the Label control that contains the calculation results in an UpdatePanel. The input controls do not need to be in an UpdatePanel.
In the update panel (with the results) have a hidden submit button:
<asp:Button ID="DoCalculate" style="display:none;" UseSubmitBehavior="false"
runat="server" OnClick="Recalculate()" />
This should be the trigger for the UpdatePanel. Then have your two input controls click that button using javascript to cause a partial postback to the "results" panel. Here is the code to add this javascript for the dropdown, for example, in Page_Load:
ddSelectedTerm.Attributes.Add("onSelectedIndexChanged",
"document.getElementByID('" + DoCalculate.ClientID + "').Click()");
Then in put the C# code to do the calculation and update the label in the 2nd update panel in the "Recalculate()" method.
This should work, and give you better layout control and less code flow ugliness then using 3 update panels.
You can just use the Focus() in the server event. For example if you have txtBox1 and txtBox2 and want to have the focus in the box 2 after write something in box 1 and both of them inside an update panel.
Only go to the TextChange event of the box 1 and write txtBox2.Focus() and after the update of the panel the focus will be in the box 2. :)
Hope helps...
I ripped out the UpdatePanel and just did jquery. Screw Microsoft.

AJAX.Net - UpdatePanel doesn't delete old content

I'm using AJAX.Net (3.5) inside a usercontrol.
The usercontrol contains an UpdatePanel, and inside the UpdatePanelthere is a MultiView.
The ScriptManager is included in the page that act as container for the usercontrol.
To switch between views the usercontrol contains a simple button.
When I click it, the View is changed so the old content is hidden and new content is displayed.
My problem is that the content isn't hidden at all.
The view changes and the new content is displayed, but the old one remains on the page.
To isolate the problem, I tried changing the multiview and switching visibility of a simple label, but the behavior is the same.
Any ideas?
oh I understand. It's all right then. The problem is not of Ajax here. It's just you cannot embed something in <table> tags. In this case, you can try something different than the <table> control. Maybe a <div> or something else. I don't know exactly what sort of situation you have. Maybe you explain the result you want to achieve so I can give you some advice.
Regards
It seems that AJAX.Net doesn't work very well if you have part of a table outside the UpdatePanel.
On my control I want to show or hide some rows of a table. I included only the tr and td tags inside the updatepanel.
To reproduce the problem:
<table>
<asp:UpdatePanel ID="UpdatePanel" runat="server">
<ContentTemplate>
<tr>
<td>
<asp:Label ID="lblToShow" runat="server" Text="Label to show" Visible="false" />
<br />
<asp:Label ID="lblToHide" runat="server" Text="Label to hide" />
</td>
</tr>
</ContentTemplate>
</asp:UpdatePanel>
</table>
If you change the visibility using:
lblToShow.Visible = true;
lblToHide.Visible = false;
The text of both labels are shown on the page (lblToHide does not hide)
If you move the table tags inside the UpdatePanel everything works fine.
call
updatepanel.Update()
after you make the changes to your updatepanel
or try
updatepanel.Controls.Clear();

Resources