As most of my readers will confirm, I'm still pursuing Silverlight 1.0. The only difficulty I'm having is that I've got some really nice ideas for applications, but they require a hookup to my database.
Maybe it's overly obvious to everyone else, but there is a very nice, simple solution to this, and it's called ASP.NET Ajax. Yeah, I know... I'm coming to this party a tad late, but better late than never, and when you come late you get to make the Grand Entrance :)
I've been kicking this around in my head for a couple weeks, rolling around ideas I see posted and actually getting more frightened of it as I go! I see Proxies, I see Ajax, I see all sorts of syntactic sugar added to functions, and it just seems like an awfully large bite to take. And, it doesn't seem like small bites are going to get me anywhere!
I spent last weekend pounding the following into WynApse.com
- ASP.NET Ajax -- into an existing site
- Web service to my database
- Full replacement of the right-hand sidebar with a Silverlight 1.0 OutlookBar-style control
Go ahead, play with the control in the righthand sidebar ... I'll wait here for you. That control is built completely from the database. I can now subdivide the one really nasty long one, "Reference", and once I make the changes in the database, it's a done deal in the sidebar!
I used the code almost exactly from the Silverlight 1.0 OutlookBar Control
that I presented at Desert Code Camp, so yes... you can rearrange the order by moving the Header text up and down even with menus open. I haven't decided if I want to retain the rearrangement, but for sure I'm not doing so yet.
Back to the beginning
Going back to Saturday morning, I first dug up some articles I had tagged. I used this one: AJAX-enable an Existing ASP.NET Web Page
to help me actually get AJAX running on the site without any issues. Once that was working, I then leaned very heavily on Michael Palermo's code that he posted the end of last week: Interactive Silverlight Using Ajax
I filled in the blank spots between those two by jumping around in ASP.NET AJAX in Action from Manning Publications
. I'd hightly recommend that book! The writing is very clear, and allowed me, without any prior knowledge, and just armed with a witless idea, to pull this all off!Page Method
I built a HelloWorld method and proceeded trying to lash it up to my master page by following Michael's PageMethod code... it just seems so simple!
That kicked my butt for a while, and I know I can hear some of you laughing... it took me a bit to find out that a Page Method only works in a Page, NOT in a MasterPage... hence the name! For a MasterPage, I need to use a Web Service.Web Service
Of course I know what a web service is, but I have always viewed them being of the 'remote' variety, or at the very least yet something else that I'd have to build and have running. I never considered how easy it is to add one to your own project. Simply "Add New Item" in Visual Studio, and selecting a Web Service allowed me to provide the interface that's been eluding me for the last few months. An article by Bipin Joshi of DotNetBips
, and his new site: bipinjoshi.net
has a great article on Developer.com
about just all this called Consuming Web Service Using ASP.NET AJAX
. Once I had a Web Service that didn't poot, I added a HelloWorld method that returned a TextBlock, and using code from Michael, I put that code into the xaml for the right-hand sidebar control... woohoo!
Using the same database layer I've been using for my site, I was able to grab data from my database in the Web Service, and then pump that data back to the client-side as fully-formed xaml ready to be run through 'createFromXaml'.
Yep, there were a few snags along the way... after a bit I realized I needed to wrap my xaml in a canvas to get createFromXaml to like it. The only time I've had to do that in the past was with animation blocks, but if it works, I like it!
The syntax gave me fits for a short period of time as well although I have to admit all of that was between the chair and the keyboard.
Once I had things sort of working, I had trouble displaying the menu blocks, and after some debug, found it had to do with links that have '&' in them. I simply converted those links with TinyURL. I can't see them from the office, but at least they're functional for everyone else.
This code is just a bit different from that of Code Camp ... I had to change the way I figure out what canvas is above or below based on Tag. With all the extra canvases thrown in, the simple loop I did in the Code Camp project didn't work. I finally reallized I had standardized on a naming scheme that allows for extensibility, and could use those names directly, so that resolved that problem. Because I don't know how many Header entries there are going to be, I name them "Selection" with an index appended. As I spin through the values returned from the Web Service, I have an index running that I use for this and other things. Therefore, I know the Header canvas entries I need for Tags are all named "Selection0", "Selection1", etc.
The only 'size' that I'm not calculating at run-time is the overall canvas size. I had to pick something, so I made it pretty large. With all the stuff on the left-hand sidebar, the page extends anyway, so with that one really long entry, it's just a bit farther. Once I subdivide that entry I can drop the height a bit.
To make the control extensible, I calculated the size of the menu based on the number of entries returned from the Web Service. This way the menu borders can snug up around the links and look nice.
The other change is a functional one. In the right-hand sidebar the way I've been using it all along, the links fired and opened in this current browser window. To get into another window, you'd have to right-mouse select that option. In Silverlight, we don't have that capability, so I chose to open a new window on each one. This is a personal preference since I use WynApse.com as a portal, and want to open new windows. I hope this isn't too annoying to anyone else.
Lashing it up
All the examples of calling a Web Service method from the client were in response to the user pushing a button. In my circumstance, I don't have that luxury, so I had to come up with a way to get the code to fire off the request to load the XAML. I tried a couple things, and eventually settled on this:
- I have a Loaded= line in my outer canvas that calls "OBCanvasLoaded"
- OBCanvasLoaded saves a copy of the main canvas and sets the plugin, then calls "callOBMethod"
- callOBMethod calls the Web Service to get the XAML for the canvas and eventually run createFromXAML
- At the end of this, a call is made to the Web Service to get the total number of Headers that I need for the rearrangement code
The default "OBar.xml" XAML file contains a TextBlock with the Text "Loading Menu...". That displays after the canvas is loaded and before the XAML is created.
I'm noticing a 'loading' problem in IE6 where, as in other applications, the Loaded= doesn't seem to always run. The canvas is alive because the "Loading Menu..." text is displayed in the default XAML file, and is on-screen, but the control doesn't get populated until I refresh. I may try other ways to control this prior to publishing this article -- I tried to use onLoad, but at least locally it didn't work right, and since I had other issues going, I stayed with the way it's written for now. Maybe next weekend...
Now that I've got data flowing into my Silverlight 1.0 canvas, there's no reason why much of the rest of WynApse.com can't be Silverlight. I've also got article concepts stacked up waiting for data access that I can now dust off and work on. And that's just WynApse.com
.... I can also do some of the same with SilverlightCream.com
! So hold onto your socks, I found a new toy :)Stay in the 'Light