Wednesday, March 28, 2012

ProfileScriptService Question

Can someone tell me where the physical location of the ProfileScriptService setting ar location. Are they stored in a cookie?

The settings are stored into Profile - which is the standard ASP.NET 2.0 profile feature.

The profile feature allows you to define the specific storage mechanism and store to use and customize via configuration in your web.config file using a provider model. Check out the docs on profile for more info...

ProfileScriptService not sticking

Is there something I'm missing. I get the drag and drop to work but I cannot get the profile setting to save. It resets the setting on a postback.

Did you try to use Fiddler or Nikhil's browser helper to monitor the exchanges with the profile service and see if there's an error message there?

ProfileScriptService Explanation

Hi,

I'm trying to understand and know all new controls Atlas has. By now, I made some examples with AutoCompleteExtender and DragOverlayExtender and all work well.

But, 'm trying to do something with ProfileScriptService and I don't know how it works. I searched information in google, in some blogs for Atlas and found one post in asp.net forum telling about other control in which there is a ProfileScripService control declared. I tested this example but I can't understand the functionality of this control.

Can someone tell me something about ProfileScriptService??

Thanks.

I am in the same boat, I am trying to get the profile script service samples from the presentations on the web to work, but they just don't work. TTYL.

hello.

well, it's just a custom proxy which wraps calls made over a web service defined in the atlas dll. so, what can you do with it? well you can get or save the properties of your profile that have been atlas enabled. to enable a property to be used, you must add it explicitly to the profileService element in the web.config file.

then, on the client side, you get the profile info by calling the load method (btw, you should also add a handler to the loaded event so that you'll be notified when the properties are loaded). to save eventual property changes, you have 2 options: autosave (in this case, you don't have to do anything) or the manual save( calling the save method).

to explain all these aspects, here's a simple example. suppose your asp.net profile has these properties:

<profile enabled="true">
<properties>
<add name="Nome" type="System.String" />
<group name="Morada">
<add name="Rua" type="System.String"/>
<add name="Porta" type="System.String"/>
</group>
</properties>
</profile>

and you want to access all of them on the client side. so, you must also add these lines to activate the atlas profile service:

<profileService
enabled="true"
setProperties="Nome; Morada.Rua;Morada.Porta"
getProperties="Nome; Morada.Rua;Morada.Porta" />

and now, you can build a simple page to get them and change them. here's some simple html that defines the page structure:

<atlas:ScriptManager runat="server" ID="manager" />

<span>Primeiro nome:</span><input type="text" id="nome" />
<br />
<span>Rua:</span><input type="text" id="rua" />
<br />
<span>Porta:</span><input type="text" id="porta" />
<p></p>
<input type="button" id="modificar" value="Actualizar perfil" onclick="actualiza()" disabled="disabled" />

and here's the jscript that might be used with it:

Sys.Application.load.add( onload );
function onload( sender, eventArgs )
{
Sys.Profile.set_autoSave( false );
Sys.Profile.loaded.add( onProfileLoaded );
Sys.Profile.saved.add( onProfileSaved );
Sys.Profile.load();
}

the profile properties are loaded after the page has loaded everything. i've also disabled autosave and set 2 handlers for the loaded and saved events. During the loaded event, i fill the controls; during the saved event, i show an alert which says that everything has been sa

function onProfileLoaded( sender, eventArgs )
{
$("nome").value = Sys.Profile.properties.Nome;
$("rua").value = Sys.Profile.properties["Morada.Rua"];
$("porta").value = Sys.Profile.properties["Morada.Porta"];

$("modificar").disabled = false;
}

function onProfileSaved( sender, eventArgs )
{
alert( "Dados perfil guardados");
}

function actualiza()
{
Sys.Profile.properties["Nome"] = $("nome").value;
Sys.Profile.properties["Morada.Rua"] = $("rua").value;
Sys.Profile.properties["Morada.Porta"] = $("porta").value;

Sys.Profile.save();
}

btw, some important observations:

* the property group sintax must use the [ ] operator
* though you can use this service from xml-script, there's currently several limitations when you have proeprties and subproperties
* pay attention if you use datetime values

Profilewebserice path doesnt work under virtual url.

I tried to find a way to replace profilewebservice with my own webservice or class, and then I found a problem. I don;t believe it is happening, but I am not sure what is wrong.

In ATLAS.js, we can find code like

Sys._Profile.WebServicePath = 'ScriptServices/Microsoft/Web/Services/Standard/ProfileWebService.asmx';

see the webservicepath is relative. When I go tohttp://mydomain.com/page/home.aspx, and do Sys.Profile.Load, I get this error:

Parser Error Message:The directive 'Page' is unknown.

Source Error:

Line 1: <%@dotnet.itags.org. Page Language="C#" ValidateRequest="false" ViewStateEncryptionMode="Never" Debug="false" EnableEventValidation="false"Line 2: CompilationMode="Never" Inherits="LinkLibrary.LinkPage" %>


Source File:/page/ScriptServices/Microsoft/Web/Services/Standard/ProfileWebService.asmx Line:1

looks like it add my virtualpath in, that doesn't sound right?

Well, it looks like your web service .asmx file has an @.Page directive in it... no? Which is wrong, if true. That's how it appears to me from what you've posted, anyway.

the asmx is ATLAS asmx.

It shows where the error happens, the @.Page is in my page.


? you said you replaced the prepackaged asmx with your own in your first post. Maybe if you posted your code, it'd be easier to help you debug it?

Oh, that confused you.

What I tried to say is I tried to find a way to use my asmx, but before I found a solution, I found a bug .

What I put on my page is just like this :

Sys.Profile.set_autoSave(false);
Sys.Profile.loaded.add(onProfileLoadComplete);
Sys.Profile.load();

and I got that error, because the test url ishttp://mydomain/page/home.aspx.

It seems the webservice add the page into its webservicepath.

If this is really a bug, I think ATLAS group should fix it. I am not sure why others didn't find it.

Line 1: <%@. Page Language="C#" ValidateRequest="false" ViewStateEncryptionMode="Never" Debug="false" EnableEventValidation="false"Line 2: CompilationMode="Never" Inherits="LinkLibrary.LinkPage" %>


Source File:/page/ScriptServices/Microsoft/Web/Services/Standard/ProfileWebService.asmx Line:1

You can tell from the error message, "ScriptServices/Microsoft/Web/Services/Standard/ProfileWebService.asmx " is what ATLAS defined in its js, but the path doesn't have "/" in front of it, I think that is where the problem from.



Have you tried giving it an absolute url just to test it and see if it's not getting hung up on where to start?


Yes, now I am using my own asmx, I set it with absolute path, it works fine under that url - /page/home.aspx
Glad to hear it!

profileService with anything other than SQL

Let's say there is no SQL Server or SQL Express on the Web Server. How would one go about implementing the whole profile thing? You can supposedly use another source for a provider? Like an XML file or something like that. Has anyone sucessfully done this, or am I the only idiot trying this? I've been scowering Google for a few hours now and I'm no further along than I was 3 hours ago.

Profiles are part of the membership provider in the .net framework. What you need to do is write a custom membership provider.

Here's a good article on what your looking for

http://www.devx.com/asp/Article/29256

Here's my google search term

http://www.google.com/search?hl=en&q=Custom+Membership+Provider+%2B+ASP.net+2.0+%2B+XML


Thanks, but I've decided to go in another direction. I'm going to use cookies instead. They're just easier to use.

As advice, cookies are a dated way to handle things likes that, and you probably should look into newer methods.

What happens, if a user has created a profile, with information about theselves, or the way they like to use your website, and then they log on from a different computer...or clear their cookies?

I understand having to remember all my passwords for every site I visit, after I clear my cookies, but if that website lost all my settings, and personal / profile information just because I cleared my cookies, I'd be pissed.


Well then I would be forced to direct them top a web page picturing a straw, and suggest they suck it up. Mind you I'm not telling you to do that, I'm just suggesting one course of action with comedic twist.

Thanks for your input anyway.

profileservice newbie question

Do the callbacks return before the Sys.Services.ProfileService.save() returns ?

Sys.Services.ProfileService.save(['myProperty'], onSaveCompleted, onProfileServiceFailed,null);

In otherwords, when Sys.Services.ProfileService.save() returns, can I assume the property is saved (barring no error occured)? or do I specifically need to wait for onSaveCompleted()

Since this is an asynchronous call, Sys.Services.ProfileService.save() will return immediatelybefore the save code on the server gets executed.

So you cannot assume that the property is saved before onSaveCompleted() is fired
because there could be errors on the server during processing in which case onProfileServiceFailed() will be fired.


Thanks! That is what I suspected but wanted confirmation.

ProfileService authentication

I use a asp.net loginbox and forms authentication (in a modalopopup) and once the user is authenticated I store the user name in a session variable.Now in a page I have to load the users profile and I am using ProfileServices.Load().I follow all the steps according to the documentation but no profile information loads on the page.

1. Is that I need to authenticate the user using Sys.Services.Authentication to use ProfileServices?

2. If I use Sys.Services.Authentication and Sys.ProfileServices then how will I store the username in a session variable if I need so?

Please help me...I am trying to explore this for the past few weeks......

Hi,

By default, no profile properties are available. For each profile property that you want to make available in a client application, add the property name to thereadAccessProperties attribute of the<profileService> element. Similarly, for each server profile property that can be set based on data sent from a client application, add the property name to thewriteAccessProperties attribute. The following example shows how to expose individual properties.

<profileService enabled="true"
readAccessProperties="Backgroundcolor,Foregroundcolor"
writeAccessProperties=" Backgroundcolor,Foregroundcolor"/>

Have you exposed individual properties?

Did the sample work on your machine?

You don't have to use Sys.Service.Authentication to use the ajax Profile service.

I don't think you read the documentation carefully as the sample is use the ajax Profile service independent.

If you have further question,please provide your code.

Best Regards,

Progess bar for a fileupload in an iFrame

hi,

I have put a file upload control in an iFrame so that I can mimic an asynch. postback. This works well, but now I would like to be able to detect when the button in the iFrame that submits the form in the iframe is clicked, so that i can trigger a "processing" message in the main page, which isn't posting back.

Any ideas on how I might accomplish this? (or if anyone has a better way to do an asynchrounous fileupload I'm very open to suggestions :-)

Hmm... I would be very interested in the direction you are headed.

Couldn't you do something with the onclientclick of the submit button in the iframe? So when that submit button is clicked in the iframe, a javascript is fired in the parent/main page that shows a "processing" message.

http://www.esqsoft.com/javascript_examples/iframe_talks_to_parent/

I am trying to do the exact same thing, would you have any example code?

thanks..

Programatically accessing Panels and Triggers (In CodeBehind at least)

I have a extensive toolkit that I have written over the past year or two that automatically generates all of my grids, dropdowns, "detail views" and other things. I wanted to start incorporating some snazzy ajax enabled inline calendars and stuff like that. However all of my code is buried deep within class files that generate the controls dynamically. A typical page that has a grid in it is simply a ASP:Placeholder tag, and a snip of codebehind saying what table the user wants to view, and the users group ID (around 3 lines of actual code).

I so to really AJAX enable this I would need a few things to work out, but I don't want to bore you all with those details. I would have tried to do it all of this in my class library already if I could, but when I instantiate a new Trigger, and type "t." to see what options I have, they are only the 4 options that I would have with an variable of type object (Equals, ToString, etc). I cannot even find the "EnablePartialRendering" flag that you need to setup on these panels on the updatepanel obj. Many of these controls have very few if any extra methods/properties/events different from the "System.Web.UI.Control" that they all inherit from.

Am I doing something wrong?

AB

hello.

is this an intellisense problem? if so, have you added the using directive to the source file?


I don't think that there is a problem with the intellisense, I mean, I have been coding for a few years now in .Net, using the intellisense to figure out how things work, without even really bothering with the documentation. It would seem that the Atlas is not to the point where it has the necessary XML markups to the source for the descriptions and what nots to kick in...

Basically, I am looking for examples, given an ASP.Net placeholder, to atlas enable it from the codebehind only, not from the designer... Make sense?

AB

hello again.

let me see if i got this correctly: you want to use the atlas server controls (ex.: UpdatePanel) from your source code files, right?

well, this should work, though i think that the intellisense info is not done yet (ie, you can see the methods/properties, but no info about them). so, your best option is to use .net reflector to see what it does (or, you can allways post your doubts here)


Yes, that is correct.

Have you seen any examples accessing the UpdatePanel from source code? The only examples I have found are in the ASPX Markup files, not the .ASPX.CS codebehind files...

The methods and properties I see are very limited, but as I see it, it would be done like:

Microsoft.Web.UI.ControlEventTrigger t = new Microsoft.Web.UI.ControlEventTrigger();
Microsoft.Web.UI.UpdatePanel up = new Microsoft.Web.UI.UpdatePanel();
up.Controls.Add(SomeLiteralControl);
t.ControlID(SomeButtonControl.ID);
t.EventName("Click");

Now, I can cause "SomeButtonControl" 's click event to change the Literals content and it will ajax that new content into the page?

AB
Ohh yeah, I also don't get the autocomplete for <atlas:UpdatePanel in my ASPX pages, any ideas on that?

AB

hello.

yep, adding triggers should be done like that ( though you still need to add the trigger to the collection maintained by the panel and this should be done until the init event of the page - btw, adding controls to the panel can't be done like that because you need a template).

what problems are you having with the updatepanel?


Hello,

I think I have the same problem. I thought I will start and try to change the example from

http://atlas.asp.net/docs/util/srcview.aspx?path=~/Server/samples/UpdatePanel.src

So the Panel2 is added to PlaceHolder on Page, but the panel doesn't update than.

Any ideas how it should be then, were to initiate the Panel.

For the moment my source code looks like that:

public

partialclassDefault6 : System.Web.UI.Page

{

privateUpdatePanel Panel2;protectedint PostBackCount

{

get

{

return (int)(ViewState["PostBackCount"] ?? 0);

}

set

{

ViewState[

"PostBackCount"] =value;

}

}

protectedoverridevoid OnInit(EventArgs e)

{

this.Init +=new System.EventHandler(this.Page_Init);this.Load +=new System.EventHandler(this.Page_Load);base.OnInit(e);

}

publicvoid Page_Init(Object sender,EventArgs e)

{

Panel2 =

newUpdatePanel();

Panel2.Mode =

UpdatePanelMode.Conditional;

Panel2.ID =

"UPForm";

Panel2.ContentTemplate =

newCTemplate(this);ControlEventTrigger pBtnClikEventTrigger =newControlEventTrigger();

pBtnClikEventTrigger.ControlID =

"Panel3bButton";

pBtnClikEventTrigger.EventName =

"Click";

Panel2.Triggers.Add(pBtnClikEventTrigger);

phPanel2.Controls.Add(Panel2);

}

protectedvoid Page_Load(object sender,EventArgs e)

{

if (IsPostBack)

{

PostBackCount++;

}

}

protectedvoid Panel3aButton_Click(object sender,EventArgs e)

{

Panel2.Update();

}

publicclassCTemplate :ITemplate

{

privateDefault6 m_pInnerControl;public CTemplate(Default6 pInnerControl)

{

m_pInnerControl = pInnerControl;

}

publicvoid InstantiateIn(System.Web.UI.Control container)

{

container.Controls.Add(

newLiteralControl(" [" + m_pInnerControl.PostBackCount +"] "));

}

}

}

thanks a lot in advance

Anna


hello again.

sorry, i didn't look with attention to your code. btw, don't add the panel like that...OnInit is called ot handle the init event, so just call method that adds the panel instead of creating a delegate...i see that you set the trigger to a panel3dbutton...where is this button placed? note that if's inside an user control, you can't do that because you need the full id of the control.


hi,

Thanks for sam clues.

But i noticed that the posted code

upadtes the panel. I changed the line

container.Controls.Add(newLiteralControl(" [" + m_pInnerControl.PostBackCount +" " +DateTime.Now +"] "));

And the date is changed every button click. Only the m_pInnerControl.PostBackCount is always zero.

Anna

Programatically add UserControls that Contain an UpdatePanel

In the release notes for the latest release it states that you can programatically add UpdatePanels now. I have a user control (ascx) that contains an UpdatePanel and a Timer to refresh the panel. When I add more than one of these controls to the page programatically the first refresh of one of the UpdatePanels blanks out all of the data in all of ascx controls. When I add the controls to the page in the aspx code everything works fine. I need to add them programatically since the number of them is configurable. I have the ScriptManager control on the page with partial refresh enabled. Is there something special I need to do when I add these controls programatically?

UserControl

<%@dotnet.itags.org. Control Language="C#" AutoEventWireup="true" Codebehind="DataPart.ascx.cs" Inherits="MS.Support.KnowledgeManagement.VisualKb.DataPart"
EnableViewState="false" %>
<div class="dataPart">
<div id="divHeader" class="dataPartHeader" runat="server">
<img alt="Collapse" style='float: right' src='images/Collapse.gif' title='Collapse'
onclick="ExpandCollapse(this,this.parentElement.parentElement.children(1))" />
<asp:Label ID="lblHeader" runat="server"></asp:Label>
</div>
<div id="divBody" class="dataPartBody" runat="server">
<asp:UpdatePanel ID="divUpdate" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<vkb:VkbBulletedList ID="blItems" runat="server" BulletStyle='disc' DisplayMode='HyperLink'
CssClass="dataPartList" NewIndicatorFontColor="red">
</vkb:VkbBulletedList>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="timerRefresh" />
</Triggers>
</asp:UpdatePanel>
<div style='text-align: center; width: 100%'>
<asp:HyperLink ID="lnkViewAll" runat="server" CssClass="dataPartLink">View All</asp:HyperLink>
</div>
</div>
</div>
<asp:XmlDataSource ID="xmlDataSource" runat="server" XPath="descendant::Items/Item"
EnableCaching="false" EnableViewState="False"></asp:XmlDataSource>
<asp:Timer ID="timerRefresh" OnTick="timerRefresh_Tick" runat="server">
</asp:Timer>

Code to add ascx to page

dp = Page.LoadControl("DataPart.ascx") as DataPart;
dp.DataType = "Article";
dp.HeaderColor = Color.LightGray;
dp.HeaderFontColor = Color.Black;
dp.HeaderText = nodes.Current.GetAttribute("Name", String.Empty);
dp.CategoryId = Convert.ToInt32(nodes.Current.GetAttribute("Id", String.Empty));
dp.BodyColor = Color.WhiteSmoke;
dp.EnableRefresh = false;
dp.XmlData = nodes.Current.SelectSingleNode("Items") != null ? nodes.Current.SelectSingleNode("Items").OuterXml : "<Items />";
td.Controls.Add(dp);

I tried a simple example just using a RadioButtonList against XML data source and everything seemed to work fine when adding dynamically. What's in the VkbBulletedList control?
Its just an override of the BulletedList control to add some custom text to each bulleted item.

programatically adding cascading dropdowns with the ability to add to the dropdownlist

I'll keep this as simple as possible, apologies in advance. Cascading dropdowns (CCD) are added to a page programatically. Each cascade dropdown (CCD) is added in a while lop based on the number of levels read in from a db table. beside each dropdown (CCD) is an add button, which when clicked pops up a modal window, allowing the user to via an update panel add to each the cascading dropdown (CCD) of choice. My problem is this I want the button beside the dropdown only to become enabled when the cascading dropdown is active/populated. So when I draw everything in theOnInit function I make the buttons beside the cascading dropdowns disabled. My Question is how do I enable them based on the (CCD) becoming active? and secondly am I doing this the correct way. Code below: Thanks in advance

While counter < SR.Item("Annello")

Lit =New Literal

If counter < 1Then

Lit.Text ="Category"

Else

Lit.Text ="Sub-Category"

EndIf

UPanel.ContentTemplateContainer.Controls.Add(Lit)

DDL =New DropDownList

With DDL

.ID ="DropDown" & counter

.Width = 250

.DataTextField ="CategoryName"

.DataValueField ="CID"

EndWith

UPanel.ContentTemplateContainer.Controls.Add(DDL)

Cascade =New AjaxControlToolkit.CascadingDropDown

With Cascade

.ID ="Cas" & counter

.TargetControlID = DDL.ID

If counter > 0Then

.ParentControlID ="DropDown" & counter - 1

.PromptText ="Please select a Sub-Category"

Else

.PromptText ="Please select a Category"

EndIf

.LoadingText ="Loading.."

.Category = counter

.ServiceMethod ="GetCategoriesPageMethod"

EndWith

UPanel.ContentTemplateContainer.Controls.Add(Cascade)

IB =New ButtonWith IB

.ID ="ADD" & counter

.Text ="add to.."

EndWith

UPanel.ContentTemplateContainer.Controls.Add(IB)

IB.Enabled =False

'''MODAL POPUP

NPanel =New Panel

With NPanel

.Style.Add(HtmlTextWriterStyle.Display,"none")

.Style.Add(HtmlTextWriterStyle.Height,"200px")

.Style.Add(HtmlTextWriterStyle.Width,"350px")

.Style.Add(HtmlTextWriterStyle.BackgroundColor,"#ffffff")

.Style.Add(HtmlTextWriterStyle.Padding,"10px")

.ID ="NPanel" & counter

EndWith

Lit =New Literal

Lit.Text ="Enter Your Category here "

NPanel.Controls.Add(Lit)

TBX =New TextBox

With TBX

.ID ="AddTBX" & counter

.Width =New System.Web.UI.WebControls.Unit(190)

EndWith

NPanel.Controls.Add(TBX)

IB =New ButtonWith IB

.ID ="OK" & counter

.Text ="OK"

'.Attributes.Add("onclick", "InsertCategory();")

EndWith

NPanel.Controls.Add(IB)

IB2 =New Button

With IB2

.ID ="Cancel" & counter

.Text ="Cancel"

EndWith

NPanel.Controls.Add(IB2)

UPanel.ContentTemplateContainer.Controls.Add(NPanel)

MP =New AjaxControlToolkit.ModalPopupExtender

With MP

.TargetControlID ="ADD" & counter

.PopupControlID ="NPanel" & counter

.OkControlID ="OK" & counter

.CancelControlID ="Cancel" & counter

.OnOkScript ="InsertNewCategory()"

.OnCancelScript ="alert('cancel');"

'.OnOkScript = "alert('OK');"

.DropShadow =False

.BackgroundCssClass ="ModalPopupBackground"

EndWith

UPanel.ContentTemplateContainer.Controls.Add(MP)

Hi

Try this,It works:

<td><asp:DropDownList ID="DropDown1" onchange="javascript:activeBtn(this)" runat="server" Width="170" /></td>

<script type='text/javascript'>
function activeBtn(ccd)
{
var strcounter = ccd.id.substring(ccd.id.indexOf("DropDown") + 8, ccd.length - 1);
var counter = parseInt(strcounter);
var theBtn = document.getElementById(ccd.id.replace("DropDown", "ADD").replace(strcounter, (counter + 1) + ""))
if(theBtn){
if(ccd.selectedIndex != 0)theBtn.disable = false;
else theBtn.disable = true;
}
}
</script>

You can add the onchange event handlers for your DropDownLists in code-behind by using this code:

DDL =New DropDownList

With DDL

.ID ="DropDown" & counter

.Width = 250

.DataTextField ="CategoryName"

.DataValueField ="CID"

.Attributes.Add("onchange", "javascript:activeBtn(this);")

EndWith

Best Regards


Gave that a go and couldn't get it to work. I see what your doing and I'm hitting the function and even if I hardcode the Button.ID to enable that one button it doesn't work, no errors but it just won't enable it... any ideas. Thanks in advance..


Hi

Sound odd,I have test it many times.I'm sure it works.

Would you please privide us with a whole demo?

Thanks


ThanksJin-Yu YinSmile


Firstly thanks for you help. It is strange that it doesn't work, the funny thing is if I change you function to the following it works, but I'd never have gotten there without your help. Again many thanks.

function activeBtn(ccd)

{

var strcounter = ccd.id.substring(ccd.id.indexOf("DropDown") + 8, ccd.length - 1);

var counter = parseInt(strcounter);

var theBtn = document.getElementById(ccd.id.replace("DropDown","ADD").replace(strcounter, (counter + 1) +""))

if(theBtn){

if(ccd.selectedIndex != 0)

{

if (theBtn.disabled) {theBtn.disabled =false;}else theBtn.disabled =true;

}

}

}


Hi

Glad to hear that it works now.I'm sorry for misunderstanding any logic of it.

Best Regards


Like I said mate, thanks ,u were 100% bang on. Appreciate the help.

Programatically Adding an AutoCompleteExtender & AutoCompleteProperties

This is from the documentation:

To extend a text box with auto-completion behavior programmatically, add an AutoCompleteExtender control to your ASP.NET Web page, and use theServicePath andServiceMethod properties to specify the Web method that returns the item list. Then for each text box that you want to add the auto-completion behavior to,add anAutoCompleteProperties server control to theControls collection of the AutoCompleteExtender. The AutoCompleteProperities component enables you to specify the target control the extender should link to and to override the ServicePath and ServiceMode setting for individual controls.

So am I to understand that I add an AutoCompleteProperties instance to the AutoCompleteExtender.Controls collection?

When I try that I get this message in VS2005:

Value of type 'Microsoft.Web.UI.Controls.AutoCompleteProperties' cannot be converted to 'System.Web.UI.Control'.

hello.

well, you just need to add them as child elements of the control since it'll automaticatically parse those elements and add them to the targetproperties property.


...forgive me for my ignorance, but how exactly is that accomplished? Can you provide a brief example?

Thanks! :)


Dim autoComplete as New AutoCompleteExtender()
Dim props as New AutoCompleteProperties()
props.TargetControlID = "txt_suggestion"
props.ServiceURL = "/WebServices/Service.asmx"
props.ServiceMethod = "GetSuggestions"
autoComplete.TargetProperties.Add(props)
Page.Controls.add(autoComplete)

Hey that worked! Thanks!

I didn't know about the AutoCompleteExtender.TargetProperties.Add method, I was trying to add it to the controls collection of the AutoCompleteExtender.

FYI - The ServiceURL property in the above code is supposed to be ServicePath (at least in the July 06 release).

Programatically adding UpdatePanel?

I want to programatically add an updatepanel control on a button click.

I tried adding a reference to Microsoft.Web.Atlas.dll and then creatinga System.Web.UI.UpdatePanel control but the app does not compile - withnamespace does not exist error.

Does anyone know what I should be doing or if this is possible at all?

Thanks !

you would need to import the following

Imports Microsoft.Web.UI

Then, you can create an instance of the UpdatePanel like this:

Dim UP As New UpdatePanel

Hope this works for you.


Thanks it works ... I was using System.Web.UI which was the problem
Now that I have this I'm trying to add content to the updatepanel.

I can set most of the properties, add triggers without problems.

However when I try to execute it - it gives an error saying "A ContentTemplate must be specified".

Whats the easist way to do this. I haven't found any documentation on programatically adding a contenttemplate.

Any help would be greatly appreciated!
I'm looking for the same thing myself and haven't found any answers.
You'll need to create a class that implements ITemplate, create an instance of that and set the content template property to that instance.

try this

protected

overridevoid OnInit(EventArgs e)

{

updatePanel.ContentTemplate =

newCompiledTemplateBuilder

(

newBuildTemplateMethod(CreateAtlasUpdateContent));

}

public

void CreateAtlasUpdateContent(Control container)

{

container.Controls.Add(yourcontrol);

}


dont know if this will come in handy with anyone but what i did to get around the template error was

have a class with the following:

PublicClass AjaxControl :Inherits Microsoft.Web.UI.UpdatePanelProtectedOverridesSub OnInit(ByVal eAs System.EventArgs)Me.ContentTemplate =New TemplateBuilderMyBase.OnInit(e)EndSubEndClass

Then whenever i needed to create a control that was surrounded by the update panel i would inherit this class and could just then put me.controls.add() as usual.

probs useless to you all, but works for me :)


Even if you got past the coding issues, you still can't add an UpdatePanel once InitComplete has fired (which is pretty early in the lifecycle) so you're not going to be able to accomplish what you set out to do, which I think was to add an UpdatePanel dynamically.

HTH

Has anyone been able to dynamically add an UpdatePanel to a page?

I got so far - and then I got the error:

"The UpdatePanel 'panel1'was not present when the page's InitComplete event was raised."

Is there any way around this?

Wade.

Programatically collapse a panel

With Beta 2, does anyone know how to programatically collapse a panel controlled by the CollapsiblePanel extender? When I click a button, I want to collapse a panel and change the ImageControl(image) to a different image...Here's another thread that addresses the same issue and has a code sample, although I don't know if it's right since it doesn't actually work for me.

http://forums.asp.net/thread/1457087.aspx


I think this iswork item 5688.

this works for me

Me.CollapsiblePanelExtender1.ExpandControlID = "Panel3"

Me.CollapsiblePanelExtender1.Collapsed = False

Programatically Create Tab Container and Tab Panels

Hi,

How can I create a tab container and subsequent tab panels within it using C# in the code behind?

Any help would be much appreciated.

Hello,

You can you the PlaceHolder Control to add the TabContainer on the page, like so: make sure to add the reference at the top - using AjaxControlToolkit;

 TabContainer container =new TabContainer(); TabPanel panel1 =new TabPanel(); TabPanel panel2 =new TabPanel(); TextBox txtOne =new TextBox(); txtOne.ID ="txtOne"; txtOne.Text ="Example Text"; panel1.HeaderText ="This is Header 1 Text"; panel1.Controls.Add(txtOne); panel2.HeaderText =" This is Header 2 Text"; container.Tabs.Add(panel1); container.Tabs.Add(panel2); PlaceHolder1.Controls.Add(container);
 
Hope this helps. 

Yep that was perfect...thanks for this!

programatically disable dropdown in Ajax updatepanel

I've searched high and low for what seemed would be a simple and frequently used method to access the properties of a drop down contained in a Ajax UpdatePanel without finding anyone who seems to have needed to do this or who has solved it. Maybe Microsoft decided nobody would ever want to do such a weird thing!

I have users with various permission levels. Depending on their level, on page load I need to disable drop downs which are contained within Ajax Updatepanels.

I can expose the properties of the UpdatePanels themselves but they do not support the enable property, only invisible which is no help.

Anyone know how this is done ?

Thanks

Aren't you able to just set the Enabled property of the appropriate DropDownList's?


Dont depends only on UI elements enable/disable state. Also enusre the User level in server side. Can pls post some code i mean in which point you want to disable the dropdown list.

Use CascadingDropDown control in AJAXControlToolKit

http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/CascadingDropDown.aspx


Hi,

Are you using the AJAX extension version 1.0.61025.0 ?

I'm using this one. The controls inside UpdatePanel can be accessed directly. For instance:

<%@. Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"> protected void Page_Load(object sender, EventArgs e) { DropDownList1.Enabled = false; }</script><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:DropDownList ID="DropDownList1" runat="server"> </asp:DropDownList> </ContentTemplate> </asp:UpdatePanel> </div> </form></body></html>

Programatically Expand CollapsiblePanel (With Lastest ToolKit)

The issue I am experiencing is due to upgrading to the latest ToolKit. I previously was able to use this code on a postback to expand a collapsible panel.

Previous Code:
Dim clp2 As CollapsiblePanelProperties = CollapsiblePanelExtender2.GetTargetProperties(Panel2)
clp2.ClientState =True
clp2.Collapsed =False

However I do understand that with the upgrade the Properties sections under each of the ToolKit controls is no longer valid. I personally liked the ability to place multiple <atlasToolKit:Properties> tags underneath ONE <atlasToolKit:CollapsiblePanel> tag. Why did you remove that?? It was easy to migrate but a hassle in regards to having to set up a new tag for each time. Anyhow... off of the soapbox.

Current Code:
Dim clp2As CollapsiblePanelExtender = CollapsiblePanelExtender2
clp2.ClientState =True
clp2.Collapsed =False

This fails to expand the Panel on a postback. Any help or solutions?

JoeWeb

I believe the ClientState value needs to be lower cased and quoted as per this post:http://forums.asp.net/thread/1325048.aspx.


Yeah after playing around with it for a little bit... I actually discovered that the following code fixed it.

Dim clp2As CollapsiblePanelExtender = CollapsiblePanelExtender2
clp2.ClientState =False
clp2.Collapsed =False

All that is different is that I set both to false.

Anyhow I figured it out about a week ago sorry I didn't post an update. Thanks!

JoeWeb

Programatically hiding Tabs in TabContainer is not hiding the HeaderText

I wanted to hide/Show one of the TabPanel programatically.

so basically I am doing this.TabContainer.Tabs[1].Visible = false;

Even thought the body of that TabPanel is hiding , the Header Text is still visible without a Tab background.

Please let me know if anyone has found a solution if faced the same problem.

Thanks

Maybe have a look at how the sample does it with script in its ToggleHidden method? Or try the .Enabled property?

it's better to use multiview and view as tab, it's works without problem

this is the code:

MultiView1.ActiveViewIndex = 2

you don't have to hide or show, just send to multiview control the index of the view you want to acitvate.


Actually there is one very simple solution:

tab.visible = false;

tab.headertext=""

And this works perfectly for me.


I use tabPanel._hide() and tabPanel._show(); on the client side. Where tabPanel = $find('tabPanelClientID');

Can anyone tell me how to do the same AND compatible with server refresh of the page... ie. If my client javascript code alters which tabs are visible using _show() and _hide(), then a button to submit the form is pressed can the tab display propertied be maintained across refreshes? hope that makes sense... :)

Currently if I do that above then returned page is reset to the original tab settings.

My scenario is...

I have 4 tabs. as the user selects from various drops downs, tabpanel2 is either hidden or kept shown. the form is eventually submitted to the server and is refreshed, but the tabs are not as they had previosuly been set!!!

I was looking for some kind of proprty like ClientState...?

help


you can also use:

TabContainer1.Tabs(3).Enabled =

False

...then you don't have to hit both the visible and headertext. You also won't have to put the text back that way either.

Dan Ribar


I have a question related to the way you are using the client-side script to show/hide the tabs. I have a tab container (clientID = tcMain) and 4 tab panels (tp1, tp2, tp3, tp4). When I tried to use the following to hide a panel I'm getting a javascript error stating "null is null or not an object". How are you able to resolve the show/hide functions?

My code:

$find('tp2')._hide(); --> failed with the above error

$find('tcMain').get_tabs()[1]._hide(); --> failed with the same error as above

$find('tcMain_tp2')._hide(); --> failed

document.getElementById('tcMain_tp2').style.visibility = 'hidden'; --> failed, could not get visibility property

Can you send me your code?


From the online sample at http://ajax.asp.net/ajaxtoolkit/Tabs/Tabs.aspx:

function ToggleTab(enable, tabNumber) {
$find('<%=TabContainer1.ClientID%>').get_tabs()[tabNumber].set_enabled(enable);
}

hides or shows the tab

function EnableTab(tabNumber)
{
$find('<%=TabContainer1.ClientID%>').set_activeTabIndex(tabNumber);
}

enables the tab which unhides it

would do the trick.

Programatically set ImageUrl in ModalPopup

Hi I have a DataList that populates from an SQL datasource. One control in the DataList is an image whose ImageUrl i am currently setting as follows:

protected void dlItems_ItemDataBound(object sender, DataListItemEventArgs e)
{
Label lblItemID = (Label)e.Item.FindControl("lblItemID");
Image imgItem = (Image)e.Item.FindControl("imgItem");

imgItem.ImageUrl ="~/Images/Items/" + lblItemID.Text +".jpg";
}


I want to be able to click the image and get a modal popup which displays a large view of the image. I have wrapped the image (imgItem) in a LinkButton. Heres the code:

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<script runat="server">
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public void SetLargeImagePath(int contextKey)
{
imgLargeImage.ImageUrl = "~/Images/Items/" + contextKey.ToString() + ".jpg";
}
</script>
<div>
<asp:DataList ID="dlItems" runat="server" DataKeyField="pkiItemID" Width="100%" OnItemDataBound="dlItems_ItemDataBound">
<ItemTemplate>
<asp:Label ID="lblItemID" runat="server" Text='<%# Eval("pkiItemID")%>' Visible="False" CssClass="ItemText"></asp:Label>
<asp:Label ID="bSpecialOfferLabel" runat="server" Text='<%# Eval("bSale")%>' Visible="False" CssClass="ItemText"></asp:Label>
<table width="100%" class="Table">
<tr>
<td rowspan="6" valign="top">
<asp:LinkButton ID="lnkImage" runat="server">
<asp:Image ID="imgItem" runat="server" Width="150px" AlternateText="Click for a larger view" />
</asp:LinkButton>
<cc1:ModalPopupExtender ID="ModalPopupExtender" runat="server" TargetControlID="lnkImage" PopupControlID="pnlLargeImage"
BackgroundCssClass="modalBackground"
OkControlID="OkButton" DynamicControlID="Label1" DynamicContextKey='<%# Eval("pkiItemID")%>' DynamicServiceMethod="SetLargeImagePath" >
</cc1:ModalPopupExtender>
</td>
<td style="width: 104px; padding-left: 5px;"><h2>Title:</h2></td>
<td><asp:Label ID="szTitleLabel" runat="server" Text='<%# Eval("szTitle")%>' CssClass="ItemText"></asp:Label></td>
<td style="width: 112px" rowspan="6" valign="middle">
</td>
</tr>
<tr>
<td style="width: 104px; padding-left: 5px;"><h2>Type:</h2></td>
<td><asp:Label ID="szItemTypeLabel" runat="server" Text='<%# Eval("szItemType")%>' CssClass="ItemText"></asp:Label></td>
</tr>
<tr>
<td style="width: 104px; padding-left: 5px;"><h2>Status:</h2></td>
<td><asp:Label ID="szItemStatusLabel" runat="server" Text='<%# Eval("szItemStatus")%>' CssClass="ItemText"></asp:Label></td>
</tr>
<tr>
<td style="width: 104px; padding-left: 5px;"><h2>Description:</h2></td>
<td><asp:Label ID="szDescriptionLabel" runat="server" Text='<%# Eval("szDescription")%>' CssClass="ItemText"></asp:Label></td>
</tr>
<tr>
<td style="width: 104px; padding-left: 5px;"><h2>Price:</h2></td>
<td><asp:Label ID="mPriceLabel" runat="server" Text='<%# String.Format("{0:c}", Eval("mPrice"))%>' CssClass="ItemText"></asp:Label></td>
</tr>
<tr>
<td style="width: 104px; padding-left: 5px;"><h2><asp:Label ID="mOfferPriceLabelStatic" runat="server" Text="Offer Price:"></asp:Label></h2></td>
<td><asp:Label ID="mOfferPriceLabel" runat="server" Text='<%# String.Format("{0:c}", Eval("mSalePrice"))%>' CssClass="ItemText"></asp:Label></td>
</tr>
<tr>
<td align="center" colspan="4">
<asp:Button ID="btnAddToBasket" runat="server" CssClass="Button" Text="Add To Basket" />
<asp:Button ID="btnBuyNow" runat="server" CssClass="Button" Text="Buy Now" /></td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:DataList>
<asp:SqlDataSource ID="dlItemsDataSource" runat="server" CancelSelectOnNullParameter="False" ConnectionString="<%$ ConnectionStrings:ConnectionString%>" SelectCommand="spREAD_tblItems" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Name="pkiItemID" Type="Int32" />
<asp:Parameter DefaultValue="BRACELET" Name="fkiItemTypeShortText" Type="String" />
<asp:Parameter DefaultValue="FORSALE" Name="fkiItemStatusShortText" Type="String" />
<asp:Parameter DefaultValue="True" Name="bPublic" Type="Boolean" />
<asp:Parameter Name="bSale" Type="Boolean" />
<asp:Parameter Name="mPrice" Type="Decimal" />
</SelectParameters>
</asp:SqlDataSource>
</div>
<asp:Panel ID="pnlLargeImage" runat="server" Width="50%">
<asp:Panel ID="pnlHeader" runat="server" Style="cursor: move;background-color:#DDDDDD;border:solid 1px Gray;color:Black" HorizontalAlign="Center" Width="100%">
<div>
<p>Larger view of item</p>
</div>
</asp:Panel>
<div>
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:Image ID="imgLargeImage" runat="server" Width="200px" />
<p style="text-align: center;">
<asp:Button ID="OkButton" runat="server" Text="OK" />
</p>
</div>
</asp:Panel>
</asp:Content>

This currently will load the ModalPopup and give Label1 the value of the pkiItemID, so i am successfully getting the item ID and passing it to the ModalPopup.

The problem is that the ImageURL is not being set. Oddly the SetLargeImagePath() method does not appear to run (breakpoints are ignored), although the Label1 value is being set??

Does anyone have any ideas how to get the image to appear in the ModalPopup?

Many thanks

Hi Assimalyst,

Assimalyst:

<script runat="server">
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public void SetLargeImagePath(int contextKey)
{
imgLargeImage.ImageUrl = "~/Images/Items/" + contextKey.ToString() + ".jpg";
}
</script>

Please contextKey should be a string type. For example, public void SetLargeImagePath(string contextKey){};

We suggest that you should use a debugging tool such as Web Development Helper or Fildder etc.

Assimalyst:

I want to be able to click the image and get a modal popup which displays a large view of the image.

Here is a sample which implement on the client side.

<%@. Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"></script><html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title>Change Picture</title> <style> .modalBackground { background-color:Gray; filter:alpha(opacity=70); opacity:0.7; } .modalPopup { background-color:#FFD9D5; border-width:3px; border-style:solid; border-color:Gray; padding:3px; width:250px; } </style></head><body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager><asp:Image ID="Image1" runat="server" ImageUrl="~/pic/upg_Business.jpg" imgUrl="../pic/upg_HomePremium.jpg" onclick="changePicture(event.srcElement.imgUrl)"/><asp:Image ID="Image2" runat="server" ImageUrl="~/pic/upg_HomeBasic.jpg" imgUrl="../pic/upg_Ultimate.jpg" onclick="changePicture(event.srcElement.imgUrl)"/> <asp:Panel ID="Panel1" runat="server" CssClass="modalPopup" Height="200px" Width="300px" style="display:none"> <asp:Image ID="Image3" runat="server" ImageUrl="~/pic/AJAX.gif"/> <asp:Button ID="Button2" runat="server" Text="Cancel" /> </asp:Panel> <ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server" TargetControlID="Button1" PopupControlID="Panel1" CancelControlID="Button2"> </ajaxToolkit:ModalPopupExtender> <div style="display:none"> <asp:Button ID="Button1" runat="server" Text="Button" /> </div> <script type="text/javascript" language="javascript"> function changePicture(imgUrl){ $get("<%=Image3.ClientID%>").src = imgUrl; $get("<%=Button1.ClientID%>").click(); } </script> </div> </form></body></html>

I hope this help.

Best regards,

Jonathan

programatically updating a panel using onblur

Ok, this is driving me nuts and I can't believe there's not a way to do this.

Basically I have a user control that dynamically adds text boxes to its control tree at runtime. I have an UpdatePanel control sitting in the top of my user control with a button and a literal control. When the button is clicked it calls a buttonclicked method in the user control that sets the literal to some text and calls the update method on the panel. It all does what it's supposed to do when I click the button and AJAX works just fine.

Now here's the problem, how on Earth do I add an onblur event to the dynamically created text boxes that will either

a) update the panel; or

b) call the buttonclicked method directly; or

c) click the button

I've tried

1txtBox.Attributes.Add("onblur","javascript:__doPostBack('ctl00_contentPlaceHolder_quoteControl_quoteButton','OnClick','');");

And a large number of variations on the above but to no avail. The problem with the above is that I don't necessarily know the full id of the button control at compile time (and even if I did I really, REALLY wouldn't want to hard code it in my class) and if it doesn't find the control then it does a full form postback making the update panel redundant. I understand that I cannot wire in a custom event handler directly to the onblur method (like you can for the text changed) so it has to be client side.

Is there a way to trigger server side events through client side script? I have to get this done even if it involves hand rolling some javascript function that I can call from the onblur attribute to call the event.

I'm a back end business tier coder so any help with the client side would be most gratefully appreciated.

Rick Edwards

Ok, I've discovered a nasty way to do this using the event hi-jacking technique or "hidden button" method found here:

http://www.dotnetjohn.com/articles.aspx?articleid=224

I'd originally shy'd away from this as it's blatantly a hack but having now spent two day researching this I can't find another way of doing it.

Basically I add a hidden button to my update panel on the parent control and wire in the button click method on the parent control code behind. I then raise the event handler in the parent user control and pass this to the child control classes that are part of my control factory. When a textbox control is manufactured by the factory I can then add the oblur attribute and wire in the button click event handler. The button click method is initialised in the parent user control and within it I call the update method for the AJAX panel.

This is great for just updating a single panel from multiple onblur events, the problem now occurs if I want to update different panels from different textbox controls, I suddenly have to start adding hidden buttons all over the place so this is far from an ideal answer.

I've just found an article on asynchronous callback features in .NET2 and it looks like I might be able to roll my own textbox control with an onblur method built in, anyone with any experience of this?

Rick Edwards


Sorry if I'm missing something, but why couldn't you just set AutoPostBack="true" on the TextBox?

Firstly the autopostback event is fired on either tabbing out of the textbox or on pressing enter and not necessarily on loss of focus. Also I don't want to fire a postback event, I actually need to fire a custom event that calls the update method on my update panel and therefore run an asynchronous postback and a partial render. I don't want to rerender the entire form.

Hope that makes sense. I tried the autopostback initially thinking along your lines but it couldn't do what I wanted.

Rick Edwards


Yes, you would be limited to whenever AutoPostBack actually fires. But then it will do an async postback (as long as it's in your UpdatePanel or set as a trigger) and run whatever handler you've set in OnTextChanged. It shouldn't reload the entire page.

If AutoPostBack doesn't do what you want, your hidden button method should work, but I'd use MyButton.ClientID to get the ID so you don't have to hardcode it (which as you said is error-prone).

Programmatic cascading dropdown repopulation

Greetings, all...

Time for yet another plaintive cry for help out to the Ajax community.

I've got a page with four cascading dropdown lists chained together. Everything is working fine.

Where my problem comes is when I add a new row into the database (via a web service) and now I want to call the parent dropdown list and repopulate it once I receive a success code from the ws. I want to be able to do this all via client-side, and I think (hope?) I'm close, but I just can't seem to get the ddl to update its options.

Here's the code so far. As you can see, I've been trying to tackle this two ways...using a $find().populate on the dropdownlist, and, alternatively, calling the web service directly. The web service call does, in fact, retrieve all the levels, including the newly added level, but I'm not understanding how to "bind" the results to the dropdown.

function AddNewLevel()
{
var txt = document.getElementById('<%= txtAddLevel.ClientID %>')
retVal = QuestionManagerWS.AddNewLevel(txt.value, OnAddLevelOk, OnTimeout, OnError);
return(true);
}

function OnAddLevelOk(result)
{
alert(result);
// This doesn't appear to do anything...it never calls the ws, etc.
$find('<%= ddlLevel.ClientID %>').populate;

// This calls the web service and gets the correct values...but how does it bind to the ddl?
//document.getElementById('<%= ddlLevel.ClientID %>');
//QuestionManagerWS.GetLevels("","Level");
}

Anyway, I would really appreciate any help that may be out there. I've looked at the stuff in the 'manual' folder of the ToolkitTests (there's usually a gem or two in there) but nothing gives any hint on how to get this to work.

Thanks in advance,

Ric

Does anyone have any ideas on this one? I'm still stumped and need some help.

I figured out a resolution to the problem.

I've blogged about it onmy site and in a few days will be putting together an article as an example to my solution.

Programmatic Button Click not causing Async Postback in FireFox

I have posted this problem in a couple of different ways in the last few weeks but that was to ask what was the cause of the problem. Through trial and error I now know the cause but not the solution.

I have an UpdatePanel with a hidden asp button within it. The problem works the same whether the button is hidden or not. If I use javascript to fire the button's onclick event a regular post back happens. If I unhide the button and manually click it an async post back happens.

This is only the case with FF2. IE7 seems to work fine.

Anyone have an idea how I can work around this?

How are you hiding the button? if you're simply setting the style to have a visibility:hidden it should work the same, if you're setting it to visible=false then it's not actually being rendered to the page and the __doPostBack() javascript you are executing (assuming you are doing it that way) is just going to do a full post back. Do you have a trigger setup for the button or do you have the ChildrenAsTriggers property set in the UpdatePanel?

Any more details you can provide will help resolve this.

Cheers,
Al


Take a look at this post and my reponses to it. The key is to set on the hidden buttonUseSubmitBehavior="false" which in FF will prevent that submission postback you are seeing.

http://forums.asp.net/thread/1660684.aspx


Check the link

http://www.jeffzon.net/Blog/post/Refresh-the-UpdatePanel-using-JavaScript-code.aspx

Programmatic Animations

We've got a new app where we are using the Accordian control like the blade interface on XBOX Live and we're building the Accordian control, and adding an updatepanel and adding a UpdatePanelAnimationExtender all programatically from a XML config document. However, I'm not sure how I can add a FadeEffect (http://ajax.asp.net/ajaxtoolkit/Walkthrough/AnimationReference.aspx#FadeAnimation). Here's thw code snippet.

Sean

AjaxControlToolkit.

AccordionPane pane =new AjaxControlToolkit.AccordionPane();

pane.ID = node.Attributes[

"Id"].Value;Label lblHeader =newLabel();

lblHeader.Text = node.Attributes[

"Header"].Value;

pane.HeaderContainer.Controls.Add(lblHeader);

pane.HeaderCssClass = node.Attributes[

"HeaderCss"].Value;

pane.ContentCssClass = node.Attributes[

"ContentCss"].Value;

UpdatePanel updater =newUpdatePanel();

updater.ID =

"updater" + node.Attributes["Id"].Value;

updater.UpdateMode =

UpdatePanelUpdateMode.Conditional;

pane.ContentContainer.Controls.Add(updater);

ProphitAccordion.Panes.Add(pane);

//Since the updater panel is created programatically we'll create our animation for the//updater panels also. Sean

AjaxControlToolkit.

UpdatePanelAnimationExtender upAnima =new AjaxControlToolkit.UpdatePanelAnimationExtender();

upAnima.ID =

"upda" + node.Attributes["Id"].Value;

upAnima.TargetControlID = updater.ID;

AjaxControlToolkit.

Animation updaAnimation =new AjaxControlToolkit.Animation();

updaAnimation.Properties.Add(

"id", ("updaAnimation" + updater.ID));//The following line doesn't work

AjaxControlToolkit.

Animation.FadeEffect upAnFade =new AjaxControlToolkit.Animation.FadeEffect();Hi Sean,

Check outthis post for details on how to dynamically create animations on the server side.

Thanks,
Ted

I know I am a little late to teh party (story of my life), but the link about doesn't work anymore and I am in desperate need of creating animations server side. Different colours for different actions, dynamically created update panels etc. This is about the only subject I can't find any info on, except this one solitary post - and now that's dead.

Programmatic client side initialization of HoverMenuPopup

I am trying to link a HoverMenuPopup to anchor tags on a page programmatically and I would like to implement something similar to the FAQ #13:
http://forums.asp.net/t/992919.aspx

This code is outdated now, and does not work.

How would it be written for the released version of the AJAX Control Toolkit?

Thank you,

Jeff

Hi Jeff,

Here is a sample made according to your requirements, please try it.

<%@. Page Language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head id="Head1" runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <div> <input type="button" onclick="addHoverMenu();" value="Add Hovermenu to HyperLink" /><br /> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="http://www.msdn.com">HyperLink</asp:HyperLink> <asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px"> Item1<br /> Item2<br /> Item3<br /> Item4<br /> </asp:Panel> <script type="text/javascript"> function addHoverMenu() { $create(AjaxControlToolkit.HoverMenuBehavior, {"id":"Repeater1_ctl10_HoverMenuExtender1","popupElement":$get("<%= Panel1.ClientID%>")}, null, null, $get("<%= HyperLink1.ClientID%>")); } </script><div style="display:none;" >Controls in this div are used to import necessary javascripts. <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton> <asp:Panel ID="Panel2" runat="server" Height="50px" Width="125px"> </asp:Panel> <ajaxToolkit:HoverMenuExtender ID="HoverMenuExtender1" PopupControlID="Panel2" runat="server" TargetControlID="LinkButton1"> </ajaxToolkit:HoverMenuExtender> </div> </div> </form></body></html>

That is what I was looking for Raymond. Now I will need to look into setting the popup location, timeout, etc.

Thank you,

Jeff


Raymond,

I've run into a bit of a snag with the popup. What I want to do is link a number of anchor tags to a single popup instance. When I use the logic of attaching behaviors to multiple anchors, certain events attached to the single popup cause the popup to jump between the anchor tags when I mouse over the popup (after hovering over a second anchor associated with the same popup).

What would you suggest I change in the below code to address this:

<%@. Page Language="C#" %>

<%@. Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI" TagPrefix="asp" %>
<%@. Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Hover Sample</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

<script type="text/javascript">
function hover(element)
{
var behaviorName = "HoverMenuExtender_" + element.uniqueID;
var behavior = $find(behaviorName);
var popupElement = $get("<%= pnlHoverPopup.ClientID%>");

if (behavior == null)
{
behavior = $create(AjaxControlToolkit.HoverMenuBehavior, {"id":behaviorName, "popupElement":popupElement, PopDelay:750, OffsetX:-200, OffsetY:16}, null, null, element);
behavior.set_PopupPosition(AjaxControlToolkit.HoverMenuPopupPosition.Bottom);
}
}
</script>

<div>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean nisl justo, sagittis
id, tincidunt nec, euismod ac, turpis. Proin ante. Sed venenatis libero ac nisi.
Nunc varius ultrices velit. Donec vestibulum interdum ligula. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nulla facilisi.
Nunc vel ligula. In <a href="http://links.10026.com/?link=http://forums.asp.net/p/1167961/1956419.aspx#1956419#" onmouseover="return hover(this);">Internet</a> nisi
eget turpis. Nunc diam. Etiam congue ipsum. Proin vitae mauris et risus ultrices
vestibulum. Phasellus laoreet lectus quis augue. Vestibulum accumsan. Curabitur
sit amet eros eu justo rhoncus eleifend. Donec semper pharetra nibh. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Pellentesque habitant morbi tristique senectus et netus et <a href="http://links.10026.com/?link=http://forums.asp.net/p/1167961/1956419.aspx#1956419#" onmouseover="return hover(this);">
Internet</a> fames ac turpis.
</div>
<asp:Panel ID="pnlHoverPopup" runat="server" Style="visibility:hidden;background-color:#ccccff;width:300px; padding:10px;color:#000000;">
<h3>
Internet</h3>
A series of interconnected local, regional, national and international networks,
linked using the Internet Protocol. The Internet is accessible via telephony wires,
HFC networks and by satellite.
</asp:Panel>
<div style="display: none;">
Controls in this div are used to import necessary javascripts.
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
<asp:Panel ID="Panel2" runat="server" Height="50px" Width="125px">
</asp:Panel>
<ajaxToolkit:HoverMenuExtender ID="HoverMenuExtender1" PopupControlID="Panel2" runat="server"
TargetControlID="LinkButton1">
</ajaxToolkit:HoverMenuExtender>
</div>
</form>
</body>
</html>

Thank you,

Jeff

Programmatic equivalent to System.Web.UI.ScriptResource attribute?

Is there a programmatic equivalent to the following attribute normally put in the AssemblyInfo file in a class library project?

<Assembly: System.Web.UI.ScriptResource("LocalizedControl.TravelInfo.js", "LocalizedControl.TravelResources", "Travel")>

I would like to use reflection to do this programmatically w/o having to link in System.Web.Extensions.

I can use ScriptManager.RegisterClientScriptResource()

to do the equivalent of

<Assembly: System.Web.UI.WebResource("LocalizedControl.TravelInfo.js", "application/x-javascript")>

but have not found a way to do the equivalent of the ScriptResource attribute.

Thanks,
Chris

Hi cpels,

Hope this will helps.

To specify how resource files are managed when an assembly is built, you include attributes in the AssemblyInfo file (AssemblyInfo.vb or AssemblyInfo.cs file).

In ASP.NET, you mark resources for the application by using theWebResourceAttribute class. To embed JavaScript files in an assembly, you use this attribute to specify the .js files as a Web resource.

To include resource files for the embedded JavaScript files, you use theScriptResourceAttribute class that is provided by ASP.NET AJAX. This attribute identifies the files specifically as resources for the JavaScript files.

The following example shows how to use assembly attributes to identify embedded scripts and their associated script resources.

' Indicates that neutral fallback resources are retrieved from ' the main assembly named MainAssembly.<assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.MainAssembly)>' Defines embedded scripts as Web resources.<assembly:WebResource("Sample.js", "text/javascript")><assembly:WebResource("Sample.debug.js", "text/javascript")>' Defines the script resources for the scripts and their types.<assembly:ScriptResource("Sample.js", "Sample.resources", "Sample.Res")><assembly:ScriptResource("Sample.debug.js", "Sample.debug.resources", "Sample.Res")>

// Indicates that neutral fallback resources are retrieved from // the main assembly named MainAssembly.[assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.MainAssembly)]// Defines embedded scripts as Web resources.[assembly:WebResource("Sample.js", "text/javascript")][assembly:WebResource("Sample.debug.js", "text/javascript")]// Defines the script resources for the scripts and their types.[assembly:ScriptResource("Sample.js", "Sample.resources", "Sample.Res")][assembly:ScriptResource("Sample.debug.js", "Sample.debug.resources", "Sample.Res")]
 

In this example, a main assembly namedMainAssembly contains an embedded release version of a client script file that is named Sample.js. The assembly also contains the corresponding debug version named Sample.debug.js. The .js files are identified as resources by theWebResourceAttribute attribute.

TheNeutralResourcesLanguageAttribute assembly attribute is used to specify the main assembly as the fallback culture. For more information, seeNeutral Resources Languages for Localization and theNeutralResourcesLanguageAttribute class overview.

The resources used by the script files are defined by using theScriptResourceAttribute attribute. The Sample.resources and Sample.debug.resources files contain resource values for the Sample.js and Sample.debug.js files, respectively.

A type named Sample.Res is generated for both the release and the debug version of the script resources. This is the type that the JavaScript code should use to access localized values. For both release mode and debug mode, the build process creates only a single type. In debug mode the resources for the release version are combined with the additional resources for the debug version.

For more information about how to create assembly-information files and the assembly metadata that is required for versioned assemblies, seeHow to: Create Versioned Assemblies for Precompiled Web Sites.

http://ajax.asp.net/docs/overview/LocalizingResources.aspx
If I misunderstood you,please let me know.
 


I am familiar with how to use the ScriptResourceAttribute in an assembly. However, this requires that the System.Web.Extensions assembly be referenced in the assembly that I am building. What I want to do is NOT have my assembly reference System.Web.Extensions, but rather use reflection to invoke various aspects of MSFT AJAX so there is no dependency on having AJAX installed. This allows my user control in the assembly to work on systems that are not using AJAX if necessary.

I have been able to implement all aspects of my MSFT AJAX functionality this way except the ScriptResourceAttribute. The ScriptManager class has the RegisterClientScriptResource() method. However, the ScriptManager class does not have a method for associating a resource with a client script the way the ScriptResourceAttribute does.

Chris

Programmatic refresh of a tab

I have been trawling the forums for a while and still have no solution to my problem. I have multiple tabs each contained within update panels. What i need is for a submit button in one tab to perform the partial update and then programatically update a second tab as well. Any ideas would be greatly appreciated.

ok i finally solved my own problem. I set the updatemode property of the updatepanel to "always". That means that even if another tab is doing an async callback the other tab is always refreshed

Hi i am looking for past one week for tabview form in asp.net 2.0 plz could you help me how to create. i have search i dont have server control in asp.net 2.0. i cant use in my company in AJAX. so, plz let me know as soon as possible.

Thanks

dilip


Hi i am looking for past one week for tabview form in asp.net 2.0 plz could you help me how to create. i have search i dont have server control in asp.net 2.0. i cant use in my company in AJAX. so, plz let me know as soon as possible.

Thanks

dilip


Set UpdateMode="Always" will slow down the page if you have a lots of data on it. If you have many tabs but only want to update one or two of them,why don't try something like:

protectedvoid GridView1_RowUpdated(object sender,GridViewUpdatedEventArgs e)

{

GridView1.DataBind();

GridView2.DataBind(); UpdatePanel2.Update();

}

Programmatical change Label.Text of a set of labels in an UpdatePanel

I write engineering solutions in VB. In most cases they need to operate in both metric and English units of measure so I need to update labels such as °F and °C appropriately. I have a number of labels in an UpdatePanel that need this sort of update. Some need to switch between °F and °C while others betweem feet and meters. Which type of units of measure to use is known at Page_Load so I thought I could just make the Label.IDs meaningful (use lblTemp1, lblTemp2 etc for temperature units) and then update their .Text property based on their ID and the units of measure. I am almost there but I can't seem to gain access to the Text property once I ahve found a Label's whose text I want to change.

Dim iAsInteger = 0

Dim myLabelAs Label

'controls I want to update are in and UpdatePanel...

ForEach ctrlAs ControlIn UpdatePanel1.Controls'check to nake sure it actually has controls first...
If ctrl.HasControls()Then'cycle through all controls in the UpdatePanel...
For i = 1To ctrl.Controls.Count
'if this is a Label then
IfTypeOf ctrl.Controls(i)Is LabelThen
'if the label ID contains "lblTemp this is a temperature unit and must be updatedIf ctrl.Controls(i).ID.ToString.Contains("lblTemp")Then
'HERE IS WHERE THE PROBLEM EXISTS...'can not gain access to the Text property

myLabel =

CType(ctrl, Label)
If uofm = SIUnitsThen 'metric

myLabel.Text =

"°C"Else

myLabel.Text =

"°F"EndIfEndIfEndIfNextEndIfNext

What error do you get? Can you post your ASP.NET code?

What kind of error you are facing ??

Post it here...


The error message I currently get is due to a casting error in the line.Unable to cast object of type 'System.Web.UI.Control' to type 'System.Web.UI.WebControls.Label'.

myLabel =CType(ctrl, Label)

At this point in the code I have found a control and determined that it is in fact a Label who's Text property I need to change. However there is no Text property for the crtl so I am trying to cast the ctrl as a Label.

Jim

Programmatically add an Extender

I'm a huge newbie when it comes down to AJAX, ASP.NET and some more of the good stuff. I hope you don't mind me sticking around here ...

I've been playing around with de CustomDragDrop library provided by Omar Al Zabir. (http://www.codeproject.com/Ajax/MakingGoogleIG.asp)
I added some transparency while dragging and the ability to call a WebService or a WebMethod (on the Page) .

I've got a static example with a few div's which are draggable into other div's, registered as dropzone's.

Now, I want to makes this useable!
I've created a DataList and I want to programmaticaly add CustomFloatingBehavior to each DataListItem.
So in the event OnItemCreated, I make a new CustomFloatingBehaviorExtender and provide the necessary properties.
Finally I put my extender in the UpdatePanel and Update it.


There's just one thing I can't figure out ...
In the static version each draggable item has JS init handler looking like this:
Sys.Application.add_init(function() {
$create(CustomDragDrop.CustomFloatingBehavior, {"DragHandleID":"DragHandle","id":"WidgetFloatingBehavior"}, null, null, $get("DragItem"));
});


My dynamic version doesn't work yet, and it think the problem might be the above lines.
I should be able to programmatically add these for each DataListItem aswell.
Has anyone got anay suggestions?

Thanks in advance!

You'll find that dragdrop stuff is currently pretty poorly supported and you might be better off rolling your own.

Personally, I do drag-drop entirely on the client side (via $create(Sys.Preview.UI.FloatingBehavior...etc) calls), and I avoid UpdatePanels like the plague. As such, I'm not as clear on the UpdatePanel lifecycle and events as I should be to answer your question, but I suspect that the clientside init event is not fired by the updatepanel on partial postback. Consider isntead looking athttp://ajax.asp.net/docs/overview/PartialPageRenderingOverview.aspx and see if you can use that pagerequestmanage.add_pageLoaded() function (or one of the other member functions) to fire off a custom javascript that runs the $create() script on new draggable items.

programmatically add calendarextender

hey all,

is this possible to attach a calendarextender control to a textbox? i'm trying to build all my controls dynamically and i'm having problems with postback/async callback behavior. Mainly not understanding what's going on? anyone have any good references on how to do this? That is, build all controls dynamically with some ajax mixed in?

thanks,

rodchar

rodchar:

is this possible to attach a calendarextender control to a textbox? i'm trying to build all my controls dynamically and i'm having problems with postback/async callback behavior. Mainly not understanding what's going on? anyone have any good references on how to do this? That is, build all controls dynamically with some ajax mixed in?

You certainly can do that.

You will just have to create an instance of the calendarextender, assign it the textbox id to its targetcontrolID property. Also make sure this web page/user control has reference to the AJAX tool kit assembly

e.g.

//first add textbox dynamically and give it an IDTextBox myTextBox =new TextBox();myTextBox.ID ="txtCalendar";//now add the calendarExtendar and assign the targetcontrol IDAjaxControlToolkit.CalendarExtender myCalExt =new AjaxControlToolkit.CalendarExtender();myCalExt.TargetControlID = myTextBox.ID;//add both controls to the form/panel control collectionthis.Form1.Controls.Add(myTextBox);this.Form1.Controls.Add(myCalExt);
/

Programmatically adding a ConfirmButtonExtender

Hi,

I cannot get my ConfirmButtonExtender to work when I add it from the code behind.

A javascript page error occurs the page loads:

Line: 2829
Char:23
Error: Sys.ArgumentException: Value must not be null for Controls and Behaviors.
Parameter name: element
Code:0

---------------

Here is the code:

-- .asp snippet----

 <asp:ScriptManager ID="ScriptMan1" runat="server"> </asp:ScriptManager> <asp:Panel ID="Panel1" runat="server"> </asp:Panel> 

---.asp.cs snippet----

protected void Page_Load(object sender, EventArgs e) { Button button =new Button(); button.Text ="Click Me"; Panel1.Controls.Add(button); AjaxControlToolkit.ConfirmButtonExtender confirmDeleteExt =new AjaxControlToolkit.ConfirmButtonExtender(); confirmDeleteExt.TargetControlID = button.UniqueID; confirmDeleteExt.ConfirmText ="Are you sure?"; Panel1.Controls.Add(confirmDeleteExt); }

----------

It's nothing special, but what am I missing?!

I am dynamically building the page, so beginning with the button on the page is not an option (which works no problem).

Thanks!

Your code works fine on my computer.


OK,

Thanks for your reply, kipo, looking at it again it seems that the error only seems to occur when using a masterpage.

Does it still work for you if you put all of it into a masterpage?


I've tried to put your code in page which is using MasterPage and it doesn't work, so you were right - error is occuring only with MasterPage. But, you can achieve it with this code:

Button button = new Button();
button.Text = "Click Me";
button.ID = "button1";
Panel1.Controls.Add(button);

AjaxControlToolkit.ConfirmButtonExtender confirmDeleteExt = new AjaxControlToolkit.ConfirmButtonExtender();
confirmDeleteExt.TargetControlID = "button1";
confirmDeleteExt.ConfirmText = "Are you sure?";
Panel1.Controls.Add(confirmDeleteExt);


Excellent!Big Smile

Thanks a lot for your help!

I thought this problem was related to IDs, but is this a bug or is this by design?

Programmatically adding ASP.net User Control to UpdatePanel

Hi All, I got a real doozy here. I have read hundreds upon hundreds of forum posts and found numerous others who have replicated this problem, but have yet to find a solution. Through testing I have been able to find the cause of the problem, and will describe it here first textually and then through a code example.

The purpose of what I am trying to do is to create a postback-free web application through the use of ASP.net AJAX UpdatePanels and User Controls. When programmatically adding a User Control to a web page through a normal postback everything works fine. All the controls within the user control are registered properly in the page and any update panels included in the user control also work properly. HOWEVER, if instead of using a full postback you use an UpdatePanel and a partial page update of the UpdatePanel the controls do not get registered with the page and events from them do not fire (for instance, a button click event never hits the event breakpoint).

Because the very same user control works fine if loaded in a full postback or dynamically added from a namespace works fine, I can be relatively sure that it only is trouble when loading via a partial page update into an UpdatePanel. I load the control via the LoadConrol method and then add it to the page via a PlaceHolder control. Theoretically, adding the User Control to the PlaceHolder should register itself and it's controls and events with the page, but it does not.

The following code sample is a UpdatePanel-free page using a user control that works, later I will show the same code with an UpdatePanel that does not.

I think I need to figure out how to register the controls and their events with the page without going through a full page postback. Any suggestions??

This example works as expected:
Default.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>23<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5<head runat="server">
6 <title>Untitled Page</title>
7</head>
8<body>
9 <form id="form1" runat="server">
10 <div>
11 <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
12 </div>
13 </form>
14</body>
15</html>

Default.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
1011public partialclass _Default : System.Web.UI.Page
12{
13protected void Page_Load(object sender, EventArgs e)
14 {
15 Control ctl = LoadControl("~/UserControlDemo.ascx");
16 ctl.ID ="UC1";
17this.UCPlaceHolder.Controls.Add(ctl);
18 }
19}

UserControlDemo.ascx:
1<%@dotnet.itags.org. Control Language="C#" AutoEventWireup="true" CodeFile="UserControlDemo.ascx.cs" Inherits="UserControlDemo" %>2<asp:Button ID="Button1" runat="server" Text="Display from UC" OnClick="Button1_Click" /> <br />
3<br />
4<asp:Label ID="Content" runat="server" Text="Content"></asp:Label>

UserControlDemo.ascx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Collections;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.WebControls;
9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
1112public partialclass UserControlDemo : System.Web.UI.UserControl
13{
14protected void Page_Load(object sender, EventArgs e)
15 {
16 }
17protected void Button1_Click(object sender, EventArgs e)
18 {
19 Content.Text ="Content Changed.";
20 }
21}

Now, consider this variation, where instead of loading the control in the PageLoad event, you do so programmatically via a button Click event. This does not work as it cause a full postback which refreshes the placeholder. Viewstate does not seem to be working in this case. (uses the same user control as the previous example)

Default.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>23<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5<head runat="server">
6 <title>Untitled Page</title>
7</head>
8<body>
9 <form id="form1" runat="server">
10 <div>
11 <asp:Button ID="Button1" runat="server" Text="Load User Control" OnClick="Button1_Click" />
12 <br />
13 <br />
14 <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
15 </div>
16 </form>
17</body>
18</html>

Default.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
1011public partialclass _Default : System.Web.UI.Page
12{
13protected void Page_Load(object sender, EventArgs e)
14 {
15 }
16protected void Button1_Click(object sender, EventArgs e)
17 {
18 Control ctl = LoadControl("~/UserControlDemo.ascx");
19 ctl.ID ="UC1";
20this.UCPlaceHolder.Controls.Add(ctl);
21 }
22}

To solve this postback problem, one would naturally want to use an UpdatePanel, like the following example. However this does not work as the controls do not seem to get registered with the page, and further nesting of user controls in UpdatePanels (to create a postback free app) are no better.

Default2.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>23<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
45<html xmlns="http://www.w3.org/1999/xhtml" >
6<head runat="server">
7 <title>Untitled Page</title>
8</head>
9<body>
10 <form id="form1" runat="server">
11 <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"></asp:ScriptManager>
12 <div>
13 <asp:UpdatePanel ID="UpdatePanel2" runat="server">
14 <ContentTemplate>
15 <asp:Button ID="Button1" runat="server" Text="Load User Control into UpdatePanel" OnClick="Button1_Click" />
16 </ContentTemplate>
17 </asp:UpdatePanel>
18 <br />
19 <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
20 <ContentTemplate>
21 <asp:PlaceHolder ID="ContentPlaceHolder" runat="server"></asp:PlaceHolder>
22 </ContentTemplate>
23 <Triggers>
24 <asp:AsyncPostBackTrigger ControlID="Button1" />
25 </Triggers>
26 </asp:UpdatePanel>
27 </div>
28 </form>
29</body>
30</html>

Default2.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Collections;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.WebControls;
9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
1112public partialclass Default2 : System.Web.UI.Page
13{
14protected void Page_Load(object sender, EventArgs e)
15 {
1617 }
18protected void Button1_Click(object sender, EventArgs e)
19 {
20 Control ctl = LoadControl("~/UserControlDemo.ascx");//loads into the page21 ctl.ID ="UC1";
22this.ContentPlaceHolder.Controls.Add(ctl);//adds to page control tree (or at least it should)23 }
24}

I know I can use the "visible" property of my controls to toggle them on and off a page to create a flicker free experience, however, my application is a database intensive app and I don't want the page running queries against the database unless I'm absolutely sure the user wants them. Rendering a 10 forms and keeping them hidden isn't a big deal, but running 10 queries that the user never wants to see is, otherwise I'd stick to that method, its works perfectly. Any suggestions? Or requests for clarification? Any help you can provide is much appreciated...thanks, Chris.

Chris, are you still working on this?

I've managed to get partial postbacks to fire events on the server from a button on a UserControl that was loaded as a result of a partial postback by an updatepanel.

Here's the code:

protected override void OnPreInit(EventArgs e){base.OnPreInit(e);if (this.Page.Request.Form["__UCTL"] !=null)this.ChangeControls(this.Page.Request.Form["__UCTL"].ToString(),null);elsethis.ChangeControls("Login","Login");}public void ChangeControls(String controlName, String controlTitle){ScriptManager.RegisterHiddenField(this,"__UCTL", controlName);this.host.ContentTemplateContainer.Controls.Clear();UserControl ctl = (UserControl)Page.LoadControl(CONTROL_DIRECTORY +"\\" + controlName +".ascx");ctl.ID = controlName;this.host.ContentTemplateContainer.Controls.Add(ctl);if (controlTitle !=null)this.host.Page.Title = controlTitle;}

I also created an Interface that has a method of ChangeControls with that signature and had my Page implement it so that my UserControls could get access to the method.


Hi Jason,

I figured out how to do it properly, you need to raise an event from the control and listen for it with the page or another control. The code to do so is also simpler than what you have. Check out this thread for more details: http://forums.asp.net/t/1123449.aspx

Feel free to msg me questions if you are confused.

-Chris

Programmatically adding ASP.net User Control to Partial Page Update / UpdatePanel

Hi All, I got a real doozy here. I have read hundreds upon hundreds offorum posts and found numerous others who have replicated this problem,but have yet to find a solution. Through testing I have been able tofind the cause of the problem, and will describe it here firsttextually and then through a code example.

Thepurpose of what I am trying to do is to create a postback-free webapplication through the use of ASP.net AJAX UpdatePanels and UserControls. When programmatically adding a User Control to a web pagethrough a normal postback everything works fine. All the controlswithin the user control are registered properly in the page and anyupdate panels included in the user control also work properly. HOWEVER,if instead of using a full postback you use an UpdatePanel and apartial page update of the UpdatePanel the controls do not getregistered with the page and events from them do not fire (forinstance, a button click event never hits the event breakpoint).

Becausethe very same user control works fine if loaded in a full postback ordynamically added from a namespace works fine, I can be relatively surethat it only is trouble when loading via a partial page update into anUpdatePanel. I load the control via the LoadConrol method and then addit to the page via a PlaceHolder control. Theoretically, adding theUser Control to the PlaceHolder should register itself and it'scontrols and events with the page, but it does not.

Thefollowing code sample is a UpdatePanel-free page using a user controlthat works, later I will show the same code with an UpdatePanel thatdoes not.

I think I need to figure out how to register thecontrols and their events with the page without going through a fullpage postback. Any suggestions??

This example works as expected:
Default.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5<head runat="server">
6 <title>Untitled Page</title>
7</head>
8<body>
9 <form id="form1" runat="server">
10 <div>
11 <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
12 </div>
13 </form>
14</body>
15</html>

Default.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10
11public partialclass _Default : System.Web.UI.Page
12{
13protected void Page_Load(object sender, EventArgs e)
14 {
15 Control ctl = LoadControl("~/UserControlDemo.ascx");
16 ctl.ID ="UC1";
17this.UCPlaceHolder.Controls.Add(ctl);
18 }
19}

UserControlDemo.ascx:
1<%@dotnet.itags.org. Control Language="C#" AutoEventWireup="true" CodeFile="UserControlDemo.ascx.cs" Inherits="UserControlDemo" %>
2<asp:Button ID="Button1" runat="server" Text="Display from UC" OnClick="Button1_Click" /> <br />
3<br />
4<asp:Label ID="Content" runat="server" Text="Content"></asp:Label>

UserControlDemo.ascx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Collections;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.WebControls;
9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
11
12public partialclass UserControlDemo : System.Web.UI.UserControl
13{
14protected void Page_Load(object sender, EventArgs e)
15 {
16 }
17protected void Button1_Click(object sender, EventArgs e)
18 {
19 Content.Text ="Content Changed.";
20 }
21}

Now,consider this variation, where instead of loading the control in thePageLoad event, you do so programmatically via a button Click event.This does not work as it cause a full postback which refreshes theplaceholder. Viewstate does not seem to be working in this case. (usesthe same user control as the previous example)

Default.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4<html xmlns="http://www.w3.org/1999/xhtml">
5<head runat="server">
6 <title>Untitled Page</title>
7</head>
8<body>
9 <form id="form1" runat="server">
10 <div>
11 <asp:Button ID="Button1" runat="server" Text="Load User Control" OnClick="Button1_Click" />
12 <br />
13 <br />
14 <asp:PlaceHolder ID="UCPlaceHolder" runat="server"></asp:PlaceHolder>
15 </div>
16 </form>
17</body>
18</html>

Default.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10
11public partialclass _Default : System.Web.UI.Page
12{
13protected void Page_Load(object sender, EventArgs e)
14 {
15 }
16protected void Button1_Click(object sender, EventArgs e)
17 {
18 Control ctl = LoadControl("~/UserControlDemo.ascx");
19 ctl.ID ="UC1";
20this.UCPlaceHolder.Controls.Add(ctl);
21 }
22}

Tosolve this postback problem, one would naturally want to use anUpdatePanel, like the following example. However this does not work asthe controls do not seem to get registered with the page, and furthernesting of user controls in UpdatePanels (to create a postback freeapp) are no better.

Default2.aspx:

1<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml" >
6<head runat="server">
7 <title>Untitled Page</title>
8</head>
9<body>
10 <form id="form1" runat="server">
11 <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"></asp:ScriptManager>
12 <div>
13 <asp:UpdatePanel ID="UpdatePanel2" runat="server">
14 <ContentTemplate>
15 <asp:Button ID="Button1" runat="server" Text="Load User Control into UpdatePanel" OnClick="Button1_Click" />
16 </ContentTemplate>
17 </asp:UpdatePanel>
18 <br />
19 <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
20 <ContentTemplate>
21 <asp:PlaceHolder ID="ContentPlaceHolder" runat="server"></asp:PlaceHolder>
22 </ContentTemplate>
23 <Triggers>
24 <asp:AsyncPostBackTrigger ControlID="Button1" />
25 </Triggers>
26 </asp:UpdatePanel>
27 </div>
28 </form>
29</body>
30</html>

Default2.aspx.cs:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Collections;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.WebControls;
9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
11
12public partialclass Default2 : System.Web.UI.Page
13{
14protected void Page_Load(object sender, EventArgs e)
15 {
16
17 }
18protected void Button1_Click(object sender, EventArgs e)
19 {
20 Control ctl = LoadControl("~/UserControlDemo.ascx");//loads into the page
21 ctl.ID ="UC1";
22this.ContentPlaceHolder.Controls.Add(ctl);//adds to page control tree (or at least it should)
23 }
24}

I knowI can use the "visible" property of my controls to toggle them on andoff a page to create a flicker free experience, however, my applicationis a database intensive app and I don't want the page running queriesagainst the database unless I'm absolutely sure the user wants them.Rendering a 10 forms and keeping them hidden isn't a big deal, butrunning 10 queries that the user never wants to see is, otherwise I'dstick to that method, its works perfectly. Any suggestions? Or requestsfor clarification? Any help you can provide is muchappreciated...thanks, Chris.

My suggestion is to not use an updatepanel for this. Google for ScottGu's blog on templating tricks; you can use a service to grab an ascx, feed it a datasource to populate the data then send the results to the page. use javascript to insert those results into the page DOM where needed, and code all your functionality in js or web methods of one form or another. It's a much cleaner / lower overhead way to do what you're trying to do anyway.


Hi Paul, I took a look at ScottGu blog, I believe this is the article you were referencing: http://weblogs.asp.net/scottgu/archive/2006/10/22/Tip_2F00_Trick_3A00_-Cool-UI-Templating-Technique-to-use-with-ASP.NET-AJAX-for-non_2D00_UpdatePanel-scenarios.aspx

Unfortunately this is not the solution I am looking for. By using this method I lose the main benefits of ASP.net: managed code, event based triggers, and the rest of the integrated features. I believe this method will cause the same problem, whatever I load into the page, the page won't be aware of it and no events will fire.

For now I am going to have to use postbacks, and I'll used the update panels for keeping things like sorting gridviews postback-less.

Thanks for the suggestion though!


I am having exactly the same problem

Can someone please help?

In similar situations before, I have used javascript and other hacks, but I feel reluctant to try to do it again. If we have a framework that can be used and can make work simpler, then It makes sense.

However, these kind of problems are frustrating, and I don't know what is the resolution. I am sure people mus thave encountered this before.

Can someone help?


This is more a dynamic controls problem than an AJAX problem.

When you dynamically add a control, you have to add it EVERY request. By moving it from PageLoad to Button_Click, you've stopped creating the control every request. You only create it if the button is pressed. That is why the events won't fire when you use controls within the user control -- because on the postback, the control doesn't even exist! The postback data is for a control that isn't in the control tree, because you didn't add it, because the event that adds it isn't firing again.

The technique to solve this is to utilize viewstate to remember that the control has been added, so that you can add it from the LoadViewState method. In your click handler, call a new method - LoadUserControl(). Define LoadUserControl to create and add the control, and to set a viewstate key, ViewState["LoadUserControl"] = true. Then override LoadViewState, and after calling base.LoadViewState, look for that viewstate key. If its true, call LoadUserControl().

New problem... Now its possible it will be added twice -- if you click the same button a 2nd time, LoadViewState will call it, and so will your button click handler. So add code to your button click handler to avoid creating it if its already loaded -- just check for the viewstate key.


Infinities...This is very interesting, thank you for your response! Unfortunately you lose me when you talk about overriding the LoadViewState. How would you modify the following code to accomplish what you are saying?

protected void Button_Click(object sender, EventArgs e)
{
Control ctl = LoadControl("~/userControl.ascx");
this.Panel1.Controls.Add(ctl);
}
Thanks!

Ok, that sounds promising. But, I don't think the situation would work still.

I have a gridView. In every row of a gridview, one of the cells contains a nested update panel. When the user clicks on a particular row, a user control dynamically gets added to the nested update panel. This works fine.

When I click on a particular button INSIDE this user control then the postback disappears, no events are triggered and nothing happens. The fact that the control probably does not exist makes sense because it justifies what happens, as in no events are fired.

However now this user control has values and data inside it, so when you are saying to load that control again, what happens to the value and the data, it looks like that data is lost. Is that not right?

Basically, in my situation AJAX cannot help. In the first place my user control should already have a viewstate in order to persist the value of data and state of the elements inside the user control. Since its viewstate is not stored, the "re-adding" will simply not work at all.


gsinha25:

However now this user control has values and data inside it, so when you are saying to load that control again, what happens to the value and the data, it looks like that data is lost. Is that not right?

No that is not right. The fact you are loading it again doesn't mean its data is lost. All controls are reloaded every request, even the statically declared ones. ViewState maintains itself through the framework, but it only maintains the data in the control, not the control itself.

gsinha25:

Basically, in my situation AJAX cannot help.

You would have the same problem if you were not using ajax. What you'd see is that the loaded user control would disappear after you click a button in it.

gsinha25:

In the first place my user control should already have a viewstate in order to persist the value of data and state of the elements inside the user control. Since its viewstate is not stored, the "re-adding" will simply not work at all.

ViewState is maintained for the control. All you have to do is make sure it exists every request. It will work, trust me.


I'm sure the formatting of this is going to be off, but here's the basic idea.

protected void Button_Click(object sender, EventArgs e)
{
LoadUserControl();
}
private void LoadUserControl()
{
Control ctl = LoadControl("~/userControl.ascx");
this.Panel1.Controls.Clear();
this.Panel1.Controls.Add(ctl);

 ViewState["Loaded"] = true;

}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);

 if (ViewState["Loaded"] != null)
LoadUserControl();
 }


Hi Infinities,

This is starting to make sense. I believe what you are talking about will work for my problem - in fact I often assumed it had something to do with the viewstate, however my knowledge and experience with it is limited. (I am new to C# and ASP.net, coming over from ColdFusion.) I am still a little confused on the the LoadViewState override. As I understand it, this event fires after the Init event in the lifecyle, and it's goal is to reload the user control if it has been added to the page. One question that pops up here, and may be what gsinha was referencing, does chages to the control also progress if it is reloading the control every time? For instance, if the user control is a gridview populated from a database and I have sorted and/or filtered it, would these sorts and filters be passed along as well?

Another question, when you assign the view state key in "ViewState[" "] = true" does it matter which key you use? And a final question, where is the savedState object coming from in the LoadViewState override?

Thanks again for your help!

P.S. I read your writeup at your website on the viewstate, I think i'll need to read it three or four more times before I can make sense of it all but amazing stuff, I love the attention to detail!


ChrisCicc:

As I understand it, this event fires after the Init event in the lifecyle, and it's goal is to reload the user control if it has been added to the page.

The general role of LoadViewState is to deserialize the control's share of the page's entire viewstate payload. Think of viewstate as just a bunch of data -- data which is associated with each control on the page. On a postback, that data is available to the control that owns it again, if it's still around that is. The role of the code I gave you is to recreate the control if it was remembered previously that it had been created.

ChrisCicc:

One question that pops up here, and may be what gsinha was referencing, does chages to the control also progress if it is reloading the control every time? For instance, if the user control is a gridview populated from a database and I have sorted and/or filtered it, would these sorts and filters be passed along as well?

Yes -- because what you have to understand is that all controls are reloaded every request. In fact, the page is completely reconstructed from the ground up every request. Remember request/response mechanism of the web is essentially a stateless process. ASP.NET and other frameworks create the feeling of statefulness through tricks like ViewState and Session state. ViewState is persisted across posts -- the controls are not. You create the control tree for the page by either statically declaring it with asp.net markup, or by dynamically creating the controls yourself. But either way, the controls start completely fresh and new every request. ViewState is then deserialized and injected into the controls, restoring them to the state they were on the last request.

ChrisCicc:

Another question, when you assign the view state key in "ViewState[" "] = true" does it matter which key you use?

No -- the idea is just to remember the fact that the control was loaded. Each control's viewstate is scoped to it, so there's no risk of using a key thats already in use by some other control.

ChrisCicc:

And a final question, where is the savedState object coming from in the LoadViewState override?

That is the deserialized viewstate associated with that specific control. The base implementation uses it to repopulate the keys stored in the ViewState statebag.


ChrisCicc:

P.S. I read your writeup at your website on the viewstate, I think i'll need to read it three or four more times before I can make sense of it all but amazing stuff, I love the attention to detail!

Thanks for reading :) I know it's quite long... but hopefully worth it.


It works!! Thanks a bundle! This solved the most important problem I had, which was loading the user control on to the page via an Update Panel. It does however bring up a few further questions that I was hoping you could help with!

First, how do I modify your code so that I can have multiple buttons load different UCs each while still using the LoadViewState override? The following code is my best attempt at it:

Instead of using the click event to call the LoadUserControl function, I did this:

  
protected void LinkButton_Click(object sender, EventArgs e)
{
MainBodyPanel.Controls.Clear();
Control ctl = LoadControl("UserControl.ascx");
MainBodyPanel.Controls.Add(ctl);

ViewState["Loaded"] =true;
}

And then in the override I did as you suggested, only added an addtional If statement for each button and control,
and sent it back to the click event function instead of the LoadUserControl so that each control could have its
own viewstate key.
While I can add new controls to the page, I cannot see them again once another control calls the .clear()
function an all that is left is the viewstate which then throws an error as it doesn't see the same control tree.
Is there a better way?
 
The second problem I have is I cannot get different user controls to communicate with each other. This is
apparent in two places. The first is I have a user control with a set of links. it is these links that call the
other user controls into the update panel dynamically. If I add the UserControl dynamically before the page
loads, the links can't see the container panel on the page. I tried using this.findControl("...").Controls.Add()
but that didn't work. So for now I have the links hard coded into the page instead being their own user control,
but it's really too complex to keep doing it that way, and it limits my nesting options.
Thanks again for any help u can provide! 
 

Ok... help me understand :) You have a bunch of links, which when one is clicked, you want to dynamically load a user control into a particular spot. Is that 'spot' different for each link? If you click on one link and then another are there supposed to now be 2 controls on the page or does the 2nd one replace the first?

I'll assume you want only 1 control at a time.

What you described sounds like it should work. I personally wouldn't explicitly call the event handler -- thats usually a bad idea. It won't cause any problems if you know what you're doing but its better design to have a 3rd method that they both call, which gives each method a clear distinct purpose (its generally bad if you have to think... who called this method?).

One think you should definitely do is give the User Control you load a particular ID. Make the ID based on something that will (1) be exactly the same every time and (2) be different for different user controls. So for example, clicking on Link1 might load UC1.ascx with ID "uc1", and clicking Link2 might load UC2.ascx with ID "uc2". The reason for this is.. well, when you dont specify an ID, any control that requires one (textboxes for example) will use an autogenerated one. But if you load controls differently on a postback than you did on the first request, the IDs wont necessarily be the same, causing problems. Assigning an ID avoids that. You shouldn't have been getting the exception you mentioned... try what I said and let me know. If you still get it, show me some code...

About your user control communication problem... I'm not following 100%. Where and when exactly are you calling FindControl, and what control are you trying to find? With controls whenever you find yourself trying to get two of them to talk directly to each other... well its usually a sign that you could improve your design a bit. The control should be self sufficient, it shouldn't be broken because something else on the page isnt just so. Rather than have the control talk to the other control, you can have it raise an event. The page then listens for the event and decides what to do with it (something which the original control doesn't much care about), which may be to push something into another control on the page (the origin of which that control doesn't much care about). Much less coupled that way.


"I'll assume you want only 1 control at a time." correct assumption. there is a panel placeholder that the controls get swapped in and out of.

I tried adding the ID as you suggested but the exception still came up. Here is the code as it currently stands:

1protected void ViewCustomerListLinkButton_Click(object sender, EventArgs e)2 {3 MainBodyPanel.Controls.Clear();4 Control ctl = LoadControl("~/UserControls/CustomersControls/CustomerList.ascx");5 ctl.ID ="CustList";6 MainBodyPanel.Controls.Add(ctl);78 ViewState["CustList"] =true;9 }1011protected void AddCustomerLinkButton_Click(object sender, EventArgs e)12 {13 MainBodyPanel.Controls.Clear();14 Control ctl = LoadControl("~/UserControls/CustomersControls/CustomerAdd.ascx");15 ctl.ID ="CustAdd";16 MainBodyPanel.Controls.Add(ctl);1718 ViewState["CustAdd"] =true;19 }2021protected override void LoadViewState(object savedState)22 {23base.LoadViewState(savedState);2425if (ViewState["CustList"] !=null)26 ViewCustomerListLinkButton_Click(null,null);2728if (ViewState["CustAdd"] !=null)29 ViewCustomerListLinkButton_Click(null,null);3031 }

The exception is thrown because when I click on a second link, it Clears the MainBodyPanel control list, and the viewstate is looking for the control list that includes the now removed control. I tried various ways I could think of to remove the viewstate but to no avail...

"What you described sounds like it should work. I personally wouldn'texplicitly call the event handler -- thats usually a bad idea. It won'tcause any problems if you know what you're doing but its better designto have a 3rd method that they both call, which gives each method aclear distinct purpose (its generally bad if you have to think... whocalled this method?)."

I couldn't figure out a way to do this. I was having each click event pass the url via the function call LoadUserControl("~/control.ascx") but I couldn't figure out how to have the loadviewstate override pass the url back when needed, so I did it as you see above.

About the communication problem, in more detail, the problem is actually with the code above. Right now that is in my pages code behind, if i make those links into a user control, and then add the control to the page with those functions in the controls code behind, it cannot see the container panel (which in this case is the MainBodyPanel). I tried using the find control method but it still couldn't see it. With the links and event handlers hard coded it works fine.

Thanks!


With this code, once you click on one of the buttons, that control will always be loaded. When you click on one button you need to 'clear' the viewstate key of the other, otherwise you'll be trying to load both controls all the time. Pretty sure that is why you are getting the error, too. Easier if you just use the same key with a different value.

About the event handler thing...

protected void Link1_Handler(object sender, EventArgs args) { Foo(); }
private void Foo() { /* load Foo, set ViewState["Loaded"] = 1 */ };

protected void Link2_Handler(object sender, EventArgs args) { Bar(); }
private void Bar() { /* load Bar, set ViewState["Loaded"] = 2 */ };

protected override void LoadViewState(object savedState) {
base.LoadViewState(savedState);

if(ViewState["Loaded"] == 1) {
Foo();
}
else if(ViewState["Loaded"] == 2) {
Bar();
}
}

You might be tempted to store the path to the actual UserControl in ViewState, that way you can just LoadControl(ViewState["Loaded"]) ... but, don't :) Treat ViewState like user input. Don't trust it. If you did it that way, the user could maniuplate viewstate in such a way that they could cause any user control in your site to load, rather than be restricted to the two you want.

Ok... so I'm still confused about your links problem. You have each link as a user control, and when clicked you want them to load their content into the parent? Controls should not modify their parent's controls. It would be better like I said, to have an event raised by the control. The page, which contains all these link controls, just hooks that event on each control and then loads the control into the appropriate place. Your FindControl probably isn't working because FindControl only finds controls within the current naming container. User controls are naming containers. So when you say, this.FindControl("foo") from within a UserControl, you're only looking for a control named "foo" WITHIN the user control, not higher. To go higher you have to call FindControl on a control thats higher. But you still have to be careful with naming containers. You could start at the page level with this.Page.FindControl("foo"), but that will only find controls named "foo" that are children of page or children of non-naming containers in page. Imagine if you had a user control that contained control with ID "foo", and then you put 5 of them on the page. Which would you expect Page.FindControl("foo") to find? Its ambiguous -- thats why it won't find ANY. Each Foo is within a naming container, so their actual IDs are "uc1$foo", "uc2$foo", etc (where uc1=id of user control 1). If you know for sure the control will be in a particular place (for you it sounds like in a master page), then go ahead and hard code that ID... but be warned, its a fragile way to do it. Another approach is to have your Page expose a "MasterContainer" property of type Control. The user controls can then just say ((MyPageType)this.Page).MasterContainer.Controls.Add(), and it will work so long as the control is on a page that inherits from "MyPage" (which, all of your pages could inherit from).Ad infinitum... lots of different ways to deal with it.