Wednesday, March 28, 2012

Vertical Tabs?

Is there a way to have the AJAX tabs line up on the left hand side, instead of on the top?

There isn't a simple property to change arrangement, but you should be able to accomplish that through overriding all of the related CSS.

Vertical tabs

I posted on in the toolkit forum but thought I would widen the audience a bit.

What's the best method these days for creating vertical tabs? I currently use the toolkit's tab control for my horizontal tabs but I want to put it in another tabcontainer that has vertical tabs (kinda like an old style TV set with channels as buttons). How are people doing this these days? Doesn't look like the AJAX tab control can be made into vertical tabs and after googling around I didn't see anything that jumped out at me.

Thoughts?

Thanks!

Craig

Hello craigcl,

I didn't see the implementation of this, but consider reading this article
http://www.codeproject.com/aspnet/WebTabControl.asp?df=100&forumid=304531&exp=0&select=1758008
and downloading the AJAX Toolkit sources helps your to create your own vertical
tabs

c> I posted on in the toolkit forum but thought I would widen the
c> audience a bit.
c>
c> What's the best method these days for creating vertical tabs? I
c> currently use the toolkit's tab control for my horizontal tabs but I
c> want to put it in another tabcontainer that has vertical tabs (kinda
c> like an old style TV set with channels as buttons). How are people
c> doing this these days? Doesn't look like the AJAX tab control can be
c> made into vertical tabs and after googling around I didn't see
c> anything that jumped out at me.
c>
c> Thoughts?
c>
c> Thanks!
c>
c> Craig
c>

It doesn't do this out of the box, but you can customize the AJAX Control Toolkit's tab control to do this. If you look at the tab's source, you'll see it renders just simple SPANs and DIVs. You can get a bit more insight on what is happening if you look atmy blog post on styling the tabs.

Hope this helps.

-Damien

Vertical tabs

What's the best method these days for creating vertical tabs? I currently use the toolkit's tab control for my horizontal tabs but I want to put it in another tabcontainer that has vertical tabs (kinda like an old style TV set with channels as buttons). How are people doing this these days? Doesn't look like the AJAX tab control can be made into vertical tabs and after googling around I didn't see anything that jumped out at me.

Thoughts?

Thanks!

Craig

Hi Craig,

Currently, there isn't a easy way to customize the tab control to show tabs vertically. But I don't think is quite difficult to implement your own one.

1. You may place several buttons vertically on the page.

2. Add some panels with corresponding content in them

3. Add javascript to control the visibility of these panels within the client side click handler of buttons

very basic question about the atlas samples

I went thru the instructions exactly (well almost...the create new item for the webservice in VS2005 is incorrect in the tutorial, it should be Create new website)

http://atlas.asp.net/docs/Walkthroughs/GetStarted/Basic.aspx

But i keep getting aError: Samples is undefined

I tried this in an attempt to fix it..but it failed too (this URL i put in the Start URL in the webservice)..I wasnt sure

<atlas:servicereferencepath="http://localhost:1169/AtlasWebService/HelloWorldService.asmx"/>

What dumb thing am i missing?

Thanks!

What do you get when you go tohttp://localhost:1169/AtlasWebService/HelloWorldService.asmx/js

Executing:

http://localhost:1169/AtlasWebService/HelloWorldService.asmx/js

Gives:

Server Error in '/AtlasWebService' Application.


Request format is unrecognized for URL unexpectedly ending in '/js'.


That is why you are getting the 'undefined Samples' javascript error. Atlas will generate the javascript objects for your webservice if you have it configured correctly. Using /js after your webservice is a good way to test if this is working.

I would recommend taking the following steps to debug this issue:

1) Double check that you are using the April CTP of Atlas. You may want to uninstall your current version and re-install the version found by going to http://atlas.asp.net/ and clicking the 'Download' button.

2) When you create your website, make sure the template you select is called _"Atlas" Web Site_. This template will give you a web.config to start from that has the appropriate configuration settings to enable generation of javascript for your web service.

3) Follow the steps in the walkthrough to create the web service. Note that the instructions are correct. Make sure you right-click on the web project (not the solution) and select 'Add New Item'. Web Service will be one of the options.

4) Test your web service by setting it as the start page and pressing F5. You should get the standard web service test page - click on the web service and make sure it works. If it does, then add '/js' to the path and see if Atlas generates javascript.

5) Follow the steps in the walkthrough to create the test page.

My guess is that your problem is caused by a configuration error. By following the steps above, you should discover what was causing the problem.
Regards,
Kyle

I'm going to assume you are using one of the wallkthroughs like this one,"Walkthrough: Creating a Basic ASP.NET 'Atlas' Web Application"

I ran into this same problem you did and the fix went like this:

When i created the new "Atlas Website", i right clicked on the root and chose "Add New", then "WebService", and put "HelloWorldService.asmx"

This did two things:
- Created "HelloWorldService.asmx" in the root of the directory
- Created "HelloWorldServer.vb" in the App_Code directory

I had then copied and pasted the code right from the sample walkthrough into the VB file....

But here was the catch, and the cause of the problem:
- The sample has "Namespace Samples.Atlas" or something the like wrapped around its classes

- Well, back on the asmx, it had put:
<%@. WebService Language="VB" CodeBehind="~/App_Code/HelloWorldService.vb" Class="HelloWorldService" %>

- And since we had just changed the classes namespace since we copied and pasted from the code on the walkthrough, we broke the link between the two, hence the "Samples in undefined" error

So my fix was to change the asmx file to say

<%@. WebService Language="VB" CodeBehind="~/App_Code/HelloWorldService.vb" Class="Samples.Atlas.HelloWorldService" %>

Problem = solved


Thanks Kyle, it was my error that i didnt read the docs closely enough...i had passed by the right click on the atlas website, and created a asp.net webservice thru the right click new webservice on the solution.

I assume that i can do the latter, later, by manually copying the relevant config entries for Atlas into the non-Atlas asp.net web.config...

thanks again

Very Basic Static Method Question - SlideShowExtender

I'm working with the SlideShowExtender to show slides from a database. I have everything working as planned, except for a major oversight which I can't figure out how to get around properly. Internally I am housing a static SlideList object which contains all the slides returned from my DAL. Inside my

static AjaxControlTookit.Slide[] GetSlides() method I am copying the SlideList interal objects into the Slide[] object and then returning it. Now for my problem, naturally because my SlideList is static, there is only one copy across each page. When more than one user is on the website at the same time, obviously they are touching the same slideshow data which is causing a lot of problems. What is the correct way to handle this solution? Was I supposed to place the GetSlides() method in a WebService.asmx webservice, or is it ok to keep them as PageMethods and then correctly keep track of the Slides on a per page basis?

I would rather keep the GetSlides() method as a static PageMethod so I don't have to completely refactor the entire project, however I am not sure how I would correctly go about having Slides and then accessing them within my static methods. I realize this is a very elementary problem, and I feel awfully silly for not knowing the answer!

THanks!

Hi,

Your question is how to return different slides upon different requests, isn't it?

Well, you may pass a parameter (contextKey) into the GetSlides method, and use it to filter some slides.

For example, let's say you plan to filter the slides according to the userName of the one is browsing the page, you assign current user name in Page_Load.

protected void Page_Load(object sender, EventArgs e)
{
this.slideshowextend1.ContextKey = currentUserName;
}

[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static AjaxControlToolkit.Slide[] GetSlides(string contextKey)
{ // return a slide array according to contextKey
}

Hope this helps.

Very confused about state in my behavior-derived class

I am writing a very simple custom control extender as a first step towards building something slightly more complex. The intention of the extender at this point is just to make a panel visible in the onmouseover event of the target control. The code below is the javascript file that is registered with the control. What I'm finding is that the property I create called _panelId is set properly when the class is initialized (I can tell by the alert box I put in set method), but the property shows up as undefined when the handler for the onmouseover event fires (once again I tested this with an alert box). It's as though the class doesn't know its own properties when it gets to the _onMouseOver function.

My appologies if I'm missing something stupid, but I've been looking at this code all afternoon and can't figure it out...

Type.registerNamespace('Ballito');Ballito.HoverPanelBehavior = function(element) { Ballito.HoverPanelBehavior.initializeBase(this, [element]);// Propertiesthis._panelId =null;// Eventsthis._onmouseoverHandler =null;this._onmouseoutHandler =null;}Ballito.HoverPanelBehavior.prototype = { initialize : function() { Ballito.HoverPanelBehavior.callBaseMethod(this,'initialize');this._onmouseoverHandler = Function.createDelegate(this,this._onMouseOver);this._onmouseoutHandler = Function.createDelegate(this,this._onMouseOut); $addHandler(this.get_element(),'mouseover',this._onMouseOver); $addHandler(this.get_element(),'mouseout',this._onMouseOut);this.get_element().className =this._nohighlightCssClass; }, dispose : function() {if (this._onmouseoverHandler) { $removeHandler(this.get_element(),'mouseover',this._onmouseoverHandler);this._onmouseoverHandler =null; }if (this._onmouseoutHandler) { $removeHandler(this.get_element(),'mouseout',this._onmouseoutHandler);this._onmouseoutHandler =null; } Ballito.HoverPanelBehavior.callBaseMethod(this,'dispose'); }, _onMouseOver : function(e) { alert('_panelId = ' +this._panelId); var panel = Sys.UI.DomElement.getElementById(this._panelId);if (panel) { panel.Visible ="true"; } }, _onMouseOut : function(e) { var panel = Sys.UI.DomElement.getElementById(this._panelId);if (panel) { panel.Visible ="false"; } }, get_panelId : function() {return this._panelId; }, set_panelId : function(value) {if (this._panelId !=value) {this._panelId =value;this.raisePropertyChanged('panelId'); } alert(this._panelId); }}Ballito.HoverPanelBehavior.descriptor = { properties: [ {name:'panelId', type: String} ]}Ballito.HoverPanelBehavior.registerClass('Ballito.HoverPanelBehavior', Sys.UI.Behavior);Sys.Application.notifyScriptLoaded();

Hi,

the problem is that you are defining delegates but you're not attaching them as event handlers:

$addHandler(this.get_element(),'mouseover',this._onMouseOver);$addHandler(this.get_element(),'mouseout',this._onMouseOut);
becomes:
$addHandler(this.get_element(),'mouseover',this._onmouseoverHandler);$addHandler(this.get_element(),'mouseout',this._onmouseoutHandler);

Hi Garbin,

Thanks very much! That did take care of my state problem. Unfortunately (for me at least), it only got me one step further. Now I get the ID of the panel just fine in the mouse over event, but the call to getElementById() returns null. The documentation on this method is somewhat limited, but it seems to say that if I use the syntax I have in my code (not specifying the parent of the element), document is assumed. My assumption has been that this refers to the document that is referencing the script, i.e. the current page. Is this a valid assumption and regardless of that is this a valid way to grab an element off the page that uses my extender control? If not, is there a way to do that?

Just to make sure I'm clear, I want to set the _panelId property to the ID of a panel control on the page housing the extender control and then to get a reference to that panel using the ID in my mouse over script so I can change properties on it. Is this possible, and if so am I trying to do it the best way?

Thanks for your help,

Lee


Hi,

are you sure that the client id of the panel matches the id that you're passing to getElementById()?

Regarding the extender, I suppose that you want to get a reference to the corresponding behavior, right? If so, you should set the BehaviorID property on the extender and then use its value to get a reference to the behavior, together with the $find method:

var behavior = $find('behaviorID');


Hi Garbin,

Thanks for your response. To answer your question, yes, I am very certain the ID of the panel matches the ID being passed to the getElementById() method. I check the value passed with the alert box immediately preceding the call to getElementById() and it definitely does match the ID of the desired panel on the page where the extender control is defined.

Regarding the second part of your post, I'm not sure exactly where your going. Do I need a reference to the behavior in the script? I was thinking that once I got the reference to the panel from getElementById(), I'd be able to directly set its properties and that that's pretty much all it would take at this point. Is this wrong? Sorry if I'm missing something obvious, just trying to get started here.

Thanks,

Lee


Hi,

sorry, I didn't want to confuse you. If you need a reference to the DOM element (the panel) then getElementById (or $get, a shortcut to access the same method) is the way to go. At this point, since you're getting an error, could you post a simple example that reproduces the problem?


 Hi Garbin,
 Here's the source for a simple page that duplicates the problem:
First, the C# class that derives from ExtenderControl and defines my little "HoverPanel" control:
using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using Microsoft.Web.UI;using System.Collections.Generic;namespace Ballito.CS{ [TargetControlType(typeof(Control))]public class HoverPanel : ExtenderControl {private string _panelId;public string PanelId {get {return _panelId; }set { _panelId =value; } }protected override void OnPreRender(EventArgs e) {base.OnPreRender(e);// Test for ScriptManager and register if it exists ScriptManager sm = Microsoft.Web.UI.ScriptManager.GetCurrent(Page);if (sm ==null)throw new HttpException("A ScriptManager control must exist on the current page."); sm.RegisterExtenderControl(this, FindControl(this.TargetControlID)); }protected override IEnumerable GetScriptReferences() { ScriptReference reference =new ScriptReference(); reference.Path = ResolveClientUrl("HoverPanel.js");return new ScriptReference[] { reference }; }protected override IEnumerable GetScriptDescriptors(Control targetControl) { ScriptBehaviorDescriptor descriptor =new ScriptBehaviorDescriptor("Ballito.HoverPanelBehavior", targetControl.ClientID); descriptor.AddProperty("panelId",this.PanelId);return new ScriptDescriptor[] { descriptor }; } }}

Next, the script file used by the control (largely the same one as in my original post):

// JScript FileType.registerNamespace('Ballito');Ballito.HoverPanelBehavior = function(element) { Ballito.HoverPanelBehavior.initializeBase(this, [element]);// Propertiesthis._panelId =null;// Eventsthis._onmouseoverHandler =null;this._onmouseoutHandler =null;}Ballito.HoverPanelBehavior.prototype = { initialize : function() { Ballito.HoverPanelBehavior.callBaseMethod(this,'initialize');this._onmouseoverHandler = Function.createDelegate(this,this._onMouseOver);this._onmouseoutHandler = Function.createDelegate(this,this._onMouseOut); $addHandler(this.get_element(),'mouseover',this._onmouseoverHandler); $addHandler(this.get_element(),'mouseout',this._onmouseoutHandler); }, dispose : function() {if (this._onmouseoverHandler) { $removeHandler(this.get_element(),'mouseover',this._onmouseoverHandler);this._onmouseoverHandler =null; }if (this._onmouseoutHandler) { $removeHandler(this.get_element(),'mouseout',this._onmouseoutHandler);this._onmouseoutHandler =null; } Ballito.HoverPanelBehavior.callBaseMethod(this,'dispose'); }, _onMouseOver : function(e) { alert(this._panelId); var panel = Sys.UI.DomElement.getElementById(this._panelId); alert(panel);if (panel) { panel.Visible ="true"; } }, _onMouseOut : function(e) { var panel = Sys.UI.DomElement.getElementById(this._panelId);if (panel) { panel.Visible ="false"; } }, get_panelId : function() {return this._panelId; }, set_panelId : function(value) {if (this._panelId !=value) {this._panelId =value;this.raisePropertyChanged('panelId'); } }}Ballito.HoverPanelBehavior.descriptor = { properties: [ {name:'panelId', type: String} ]}Ballito.HoverPanelBehavior.registerClass('Ballito.HoverPanelBehavior', Sys.UI.Behavior);Sys.Application.notifyScriptLoaded();

Finally, the markup for a simple page that uses the control:

<%@. Page Language="C#" %><%@. Register Namespace="Ballito.CS" TagPrefix="ballito" %><!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>ASP.NET AJAX Behavior Sample</title></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <asp:Panel ID="Panel1" runat="server" BackColor="Cyan" Height="50px" Width="125px" Visible="False"> </asp:Panel> <asp:Button runat="server" ID="SampleButton" Text="Submit Form" /> <ballito:HoverPanel ID="hoverPanel1" runat="server" TargetControlID="SampleButton" PanelId="Panel1" /> </div> </form></body></html>

The behavior I find is that when I run the page and mouse over the button, I can tell the onmouseover event in my control does fire since the alert box in it is displayed. This is the alert box right before the call to getElementById(). As I said in the last post, the alert box shows the value of the _panelId property properly ("Panel1" in this case). The problem is that the alert box that fires right after the getElementById() call shows that the value returned by getElementById() is null instead of [object].

Thanks for the help,

Lee


Hi,

you are setting the Visible attribute of the Panel to false. This means that the Panel won't be rendered on the page and this is the reason why you are getting a null reference.

If you want to hide the panel, you could style the Panel using display:none or visibility:hidden


Hi Garbin,

Well this finally got me going down the road. I'm finding there is still a lot for me to figure out, but I'm starting to get things to work in some sort of expected manner and that's usually what it takes for me to get movement when learning something new. Thanks for all your help.

Lee

Very long loading times on II7 free hosting sites

I've deployed a recently started project on 2 IIS 7 free hosting companies, hostmysite.com and maximumasp.com.

I have encountered big loading times on the whole site, but mostly at AJAX parts. For example I have a few cascade drop down lists and it takes 2-3 seconds to populate 1 dropdown with 3-4 listitems when the user selects something in the first dropdown. On my localhost it happends faster than you blink (E6660, 2 GB RAM).

Have anyone tried out this services ? Its their fault for the big loading times or maybe it's something from my code ? I'm really worried about this and I have no other testing option except this free hosts.?

Well, how does it run for you in development?

You really need to look at what's slow. Is it your app or is the Internet Connection? Is it latency (ie. startup of the app) or is it request times that are slow.

Hosting sites often have issues with very short Application Pool timeouts that cause the entire app to shut down and are then slow to restart. However, this should not be an issue if you use the site for a number of hits in a row.

+++ Rick --


I'd recommend you first use something like FireBug (or the IE equivalent) to monitor the network traffic your partial postbacks cause. It sounds like the network traffic is your bottleneck. Especially watch out for huge ViewStates that get uploaded with every partial postback.


On developing machine it's instant.

I used firebug to do some texts on a page. I have 2 dropdown lists in an update panel and below (outside the update panel) I have a huge gridview. The problem seems to be that gridview's huge viewstate that gets uploaded/downloaded with every partial postback asgt1329asaid.

Now I know the problem. But whats the solution ? Why does the gridview's view state gets uploaded/downloaded everytime even if the gridview is not inside the update panel ?


Unfortunately, the full page's ViewState is sent back and forth on any partial postback. There's no way around that. Though, most of the time there are controls that you can disable ViewState on to minimize it. Or, if you're doing a lot of postbacks, you might consider rebinding controls on the server side, instead of using ViewState to persist them (viability of this really depends on how your page works).

The other option is that you can use web methods/services to replace some of your heavily used UpdatePanels with JSON communication:

http://ajax.asp.net/docs/tutorials/ASPNETAJAXWebServicesTutorials.aspx


Thanks for all the possibilities you recommended me.

Knowing almost nothing about them all I would also like a suggestion about what method to use. I'm trying to make minimize partial postbacks times because 3 seconds for populating a dropdown list with 5 items it not an acceptable time at all.

Using Web Services seems to most suitable method, but as I said, I know almost nothing about them all so I would like to hear an opinion from someone who knows more than me.


You should attempt to do both. Optimize your ViewState and replace partial postbacks with leaner alternatives when it's possible.

Most controls that are based on form elements can have ViewState eliminated. This is beneficial, even in non-AJAX scenarios, but will especially help cut down on the network footprint of your partial postbacks.

Web Method/Services are great. However, you can't (realistically) use them for anything that needs to modify ViewState. I'd say they're especially well suited to read-only operations that display changing data. A stock ticker, for example. On the other hand, manipulating a GridView with Web Methods would be tough. For more info on web methods vs. UpdatePanels, take a look at this:http://encosia.com/index.php/2007/07/11/why-aspnet-ajax-updatepanels-are-dangerous/

Also, don't forget the AjaxToolkit. For your dropdown, you could use the cascading dropdown extender in the toolkit to do half the work for you (just need to make the web service for it and you're done).


Allright I've used cascadeDropDown extender for my 2 dropdowns and wrote a WS to handle them. The problem is now that depending of the selection I make in the first dropdown I also want to display or hide a label or change it's Text value. This cannot be done within the WS so I'm back to where I started.


I believe those dropdown extenders fire the normal client side events. So, you could handle EndRequest() to change cosmetics like a text label or div visibility on the client side (or do it on BeginRequest, if you wanted).

Basically, if it's a read-only, cosmetic change, try to do it in client script if you can.


If you are looking for super lightweight grid which support binding data from a web service call try thishttp://dotnetslackers.com/articles/ajax/ASPNETAjaxGridAndPager.aspx


Could you please detail this gt1329a ?