Thursday, February 22, 2007
Wednesday, February 14, 2007
Simple web chart example
http://www.sitepoint.com/article/asp-net-graphs-raise-the-bar
Tuesday, February 13, 2007
Javascript in Asp.Net 2 examples
http://dotnetslackers.com/articles/aspnet/JavaScript_with_ASP_NET_2_0_Pages_Part1.aspx
Monday, February 12, 2007
General .net code samples
Thursday, February 08, 2007
Office 2007 and RSS feeds
My basic issue with RSS readers I've tried is that RSS feeds are spread apart as much as possible. By this I mean to read blogs, you generally have to click on an object for each blogger to read their new blog for the day, then onto the next blog that's been updated today. It can take a few clicks to read the latest blogs.
My goal was to always have one central feed, or perhaps 3 or 4. Maybe like Programming, News, Sports, Fun. So every programming blog I subscribe to goes into one folder. So when I log in that morning I have simply have 5 unread Programming blogs.
So think about email with Outlook. You can sort by sender, date, subject, conversation (great for newsgroups BTW) and where you want you can send certain emails to other folders to keep them out of the "main stream". You log in that morning and X emails await you, which is great. So when I heard Office 2007 would support RSS, I figured this would be very similar and allow such flexibility. I was wrong... kind of.
By default Office 2007 adds each feed to a new folder, and doesn't make it obvious there is an alternative, which I find frustrating. Once added, each folder is completely separate and can't be merged into one giant feed. However in each folder, you still have all the ordering features, but what's the point when it's all one blog.
So this is how I've setup my RSS in Outlook 2007. It's the long way but worth it in the end I think, solving the problem I had.
- Right Click on RSS Feeds and choose "Add a New RSS Feed"
- Enter the URL for the RSS Feed (usually found by clicking the orange antennae symbol and copying the URL it takes you too)
- Click Add, and when the next dialog appears click Advanced.
- Click Change Folder
- While RSS Feeds is highlighted click New Folder and type a general name for you feed like Programming
- Highlight Programming and press OK
- Also notice the Downloads section has a "Download the full article as .html..." I click that as some really good posts include images which make things worthwhile.
- Press OK and then Yes to finish it off, and you have your feed going to a Programming folder.
There is absolutely nothing stopping you adding more feeds to this folder, with the added benefits, that if you check your feeds folder today, the Programming folder will contain all useful programming feeds for today, in full html format and you don't need an external program to achieve this. And all in your new install of Office 2007, which I know for me, adds a nice reason to upgrade.
Sunday, February 04, 2007
Good .net code links
http://www.codeplex.com/
http://www.gotcodesnippets.net/
http://www.gotdotnet.com/
Thursday, February 01, 2007
wpf/e in the real world
Pros
The real beauty is the language behind wpf/e is XAML, which is a large improvement from standard winforms or HTML programming, and in fact takes some of the best parts of each.
As an example, winforms is pretty lacking when it comes to anything 3D. WPF, and even wpf/e gives an easy way to make a control seem like it's been moved elsewhere in 3D by using transformations. But even better like HTML which allows you to store GUI objects in GUI objects a lot easier than winforms, you can do that transform to the top level GUI object and the inner objects all do the transform too. This is the case with events too. You can add click events which cascade down the child objects, which is not possible in winforms.
So this is all good, but considering this is avialable for many browsers and OS's it's even better. From what I've played with you can do some real magic in a browser using wpf/e which brings us much closer to the browser nirvana. That is where web forms are a better solution to a solid windows app. I'd hope to get all happy and optimistic here, but the cons are yet to come.
I'm not an expert on the subject but some of the above is just the beginning, as the project is still evolving and I haven't dug nearly deep enough just yet.
Cons
OK, there had to be a downside to such a nice multi platform graphics platform.
wpf/e is as mentioned a cut down version of WPF. And I love some of the features they have squeezed in but, there is a massive issue here... javascript. It is the backend language for wpf/e, which has me deeply concerned. Forgetting those poor folk who run their browsers without javascript of course (as most others have already since AJAX appeared on the scene), javascript programming is just not fun or easy. We started asp.net sites without really needing javascript, and now with Microsoft AJAX and wpf/e they want us to have half our code in javascript.
In some way I can forgive the above as javascript at least is fairly common. My biggest concern is lack of databinding. In such a modern language, Microsoft knows that data is a central point, but have opted to not support data at all, a very strange move. Are they worried that such a comprehensive browser plugin would eliminate the need for windows? Because as it is, to bind any data to any wpf/e control needs:
- javascript
- AJAX
- Web services (technically not needed but easier)
- more javascript to get the AJAX data returned
- some method of filling the data a the wpf/e data template
- some more javascript to put the templates into a grid like structure
The above isn't friendly enough for most, and in fact brings me to think they simply trying to match Flash with this version.
OK, I finally mentioned it, yes Flash. Personally, I'm not a big fan of Flash at all, but it is pretty hard to avoid. The good Flash programmers improve your experience on the web, others, not so much. The percentage of sites that are improved are fairly low by the way. Now that I bring Flash into the equation, a quick comparison needs to be made:
- I'm not going to say wpf/e is better graphically, as I've seen some pretty impressive Flash pages over time. But I will say it seems to be at least match.
- Users aren't always happy to install a plugin to get a page to work, especially after installing Flash after weeks/months/years of websites using it. The only thing in MS's favour is it's MS, which most people would at least trust.
- Where MS could have moved forward in leaps and bounds would have been a solid DB backend, but it didn't happen. With this programmers would have/will flock to wpf/e in droves. Even hooking up to a web service without javascript code would be a good start if it's possible
OK, so that's about my rant for now. Personally, I'm in no hurry to program for wpf/e (or Flash) especially when Microsoft AJAX brings forward so much more than what asp.net did but with all the high quality DB support that asp.net has, and of course works anywhere without plugins.
All I can hope is wpf/e improves enough to keep MS interested, as it has plenty of potential if given time to evolve.
Wednesday, January 24, 2007
The Perfect Service
http://www.15seconds.com/issue/040624.htm
Sunday, January 14, 2007
Google Checkout example for .net
http://www.windowsdevcenter.com/pub/a/windows/2007/01/09/build-a-net-app-for-google-checkout.html?CMP=OTC-U49S05779020&ATT=Build+a+NET+App+for+Google+Checkout
Thursday, January 11, 2007
Reading and writing Excel in .net 3.0
http://www.codeproject.com/useritems/ExcelPackage.asp
Wednesday, November 08, 2006
Vista is RTM and pricing.
http://windowsvistablog.com/blogs/windowsvista/archive/2006/11/08/windows-vista-releases-to-manufacturing.aspx
While plenty of work has been going on in Microsoft, a lot of discussion has been happening outside discussing the features, version comparisons and pricing of Vista.
My current reasons why I would upgrade to Vista from XP include:
IIS7
Improved Media Centre
Nice built in search
Easier to find and open any programs
Built in .net 3.0, IE7, Media Player 11, DVD movie maker
Excellent backup restore options
Repartioning tool
Use USB key to speed up computer (at $Au27 for 1GB very cheap speed increase)
And why I wouldn't:
Home Premium doesn't have remote desktop or IIS, which means it's a downgrade from XP media centre
Too many annoying popups when doing daily tasks
May still not be stable enough compared to XP
Price, in Australia at least
So what do I mean by price in Australia? Take a quick look at two upgrade options I have and compare US prices to Australian prices:
Home Premium Upgrade
$US in US = $159
$US in Au = $230
Ultimate Upgrade
$US in US = $259
$US in Au = $380
That's RRP, so it's likely big US chains will come out even cheaper (as should a few Australian stores to). But have a look at the gap between Ultimate upgrade prices in Australia and the US. Rediculous!
I'm certainly going to heavily investigate my options of getting a copy in the US, even though I know it will be locked down pretty tight.
That said I'm willing to upgrade and hoping to get Ultimate given the few extra features that I will use.
Monday, November 06, 2006
.net 3.0 official release
Check out all the usual downloads for the official version here:
http://www.netfx3.com/blogs/news_and_announcements/archive/2006/11/06/.NET-Framework-3.0-has-been-released_2100_.aspx
And of course don't forget the Virtual labs to help you get up and running:
http://labs.netfx3.com/
UPDATED:
Here is the whole list of links including the Office 2007 downloads for Visual Studio and AJAX for asp.net:
http://msdn.microsoft.com/vstudio/devsolutions/
And since it's supported on XP and every version of Vista, I'm looking forward to getting stuck into WPF especially over the next few months now.
Thursday, November 02, 2006
Vista retail licensing. Microsoft backs down.
Vista retail licensing has been a well discussed topic over the last few weeks. In short for someone like me it went like this:
As long as I only upgrade my machine hardware once in the years that I want to use Vista as my OS, I'm fine. Once I upgrade a 2nd time though I need to buy a new version of Vista. To me this is scarey, and means I'd really want to make sure the next hardware upgrade would be a good one, as I'm not that happy with outlaying hundreds of dollars after only owning Vista for a couple of years.
BUT NOT ANY MORE!!!!!
Microsoft have officially backed down and will now allow a single user to upgrade their hardware as much as they like. For me that takes the expected usage from 2-3 years, to whenever a better OS worth buying comes out, as I'm more than happy with my core hardware like the case, and will most likely just upgrade components as mine get out of date.
Take a look at the official blog about this:
http://windowsvistablog.com/blogs/windowsvista/archive/2006/11/02/news-revision-to-windows-vista-retail-licensing-terms.aspx
Very good news from Microsoft, thanks for listening to the 5-10% of people who would actually care about this change of licensing.
Monday, September 25, 2006
WPF for beginners: Hello world
Getting started:
- In Visual Studio 2005 goto File -> New -> Project from the main menu
- Select Project Type "NET Framework 3.0"
- Choose "Windows Application (WPF)" (note that XAML Browser Application would be near identical code, except will run in a browser)
- Change the name and location if needed and press OK.
XAML
XAML is the new forms designer technology for WPF. I'm not going to go into detail about XAML, but there are some cool features you'll see in these examples. Firstly, controls have become infinitely more flexible than Winforms. Take for example a Button. Like Winforms you have basic properties like Background and Foreground colors, and can simply put some text in between the tags and have a button. Add a Click event and off you go ... BUT XAML allows you to take that text away and put a Panel in the Button tags. And in that panel, you can put other controls. If you want your button to have 3 images side by side, with text going diagonally across the images, you can. Not only for buttons, most controls allow this feature. The "content" area of a button or other controls only allow one child, but once that child is a panel, you suddenly open up a whole new world.
Another cool feature is the Properties design. Within your Button tag, you can simply put a Background="White" to set the Background property, much like Winforms. But again, you can open this up, but adding a tag after the Button tag, like <Button.Background>. Inside those tags, you suddenly have a lot of freedom again, and can add images, gradients, etc. Other Properties can do other sorts of things too, and in many cases I've found it beneficial adding these tags outside the main tag, as flexibility follows.
Also remember that XAML has inheritence built in nicely. Controls can inherit properties from the parent controls, which is handy for databinding etc. Styles also can inherit from other styles, which makes building a consistant but complicated GUI relatively easy. And again with animations, like scaling a control to be bigger, child object simply scale with it, and even other animations will apply over that new size.
Resources
Very widely used, we can store styles in a Resource section, in this case <Window.Resources>, which would most likely come straight after the root Window tag. In XAML, these resources can be referenced by calling StaticResource and using the x:Key name. So if we have a Style in the Windows.Resources section, we need to give it a key like <Style Key="StandardButtonStyle">. To use this style <Button Style="{StaticResource StandardButtonStyle}">.
Style
A lot of power comes from our style objects. You can take these as far as you want to really. Like CSS stylesheets for HTML we can setup standard looks for our controls, setup styles to target specific control types (ie. all buttons on a form), inherit from other styles and even triggers styles and animations from events and properties of the control. What was formerly not possible, or at least very tricky with lots of code, can now take only a few lines of XAML and effect many controls.
As mentioned earlier a Style must have an x:Key so that other controls can find it using StaticResource. Also mentioned we can inherit from another style using BasedOn="{StaticResource EarlierStyle}". This allows you to build styles from a basic look adding extra functionality as you go up. A style can also target a type of items like this TargetType="x:Type Button". Note that if you target a type, you can't inherit from a style that targeted another type, so take care in building your styles up properly.
Setters give you the most basic functionality in a style. <Setter Property="Background" value="Red"> will cause any control that uses that style and doesn't override Background to have a Red background. By splitting Value out into another tag you can also get more advanced behaviour <Setter Property="Background"> <Setter.Value> <LinearGradientBrush>
Triggers allow you to change the look, or add animations when properties are certain values or events are triggered. By allowing us to do a lot more visual work in the XAML, we are getting closer to the true separation of GUI and code behind. In Winforms we have a lot of code behind to keep the application looking right, but with XAML it's more than likely possible to keep most of that code in nice clean XAML.
To perform an animation based on an event like Loaded or Click <Style.Triggers> <EventTrigger RoutedEvent="Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ColorAnimation>
To have a Trigger based on a property choose <Trigger Property="Control.IsMouseOver" Value="true"> <Setter Property="Background" Value="Red"> <Trigger.EnterActions>... <Trigger.ExitActions>. In this case when the property IsMouseOver is true, we can change the background to Red, and when it's false, it will use the default style. Also by adding tags EnterActions and ExitActions we can start animations when the property becomes true and when it becomes false.
Very cool.
Effects
I have only touched upon effects in this example, but like styles, effects are available and work the same for most controls. The beauty of WPF is you learn how to use an effect, then you can use that effect on buttons, panels, textbox's etc, as effects are applicable to the UIElement on which all those controls are based upon. Many effects add to the GUI feature set, such as a blur effect, glow, drop shadow, bevel, emboss. These can also be animated, as shown in this example.
Animation
In XAML, we again have struck gold with animations that can be done without writing a line of code behind or using timers. WPF uses it's internal timeline to get property values from one value to another. And once again, proeperty is fairly vague allowing us to simply make a control disappear by setting it's Opacity from 1 to 0, or it can be setting complex transformations of the control, parallel to other property changes.
To setup an animation we use the Storyboard seen earlier <BeginStoryboard> <Storyboard> <DoubleAnimation TargetName="CloseButton" TargetProperty="Opacity" From="1" to="0" duration="0:0:0.5" autoreverse="false"> ... In this case DoubleAnimation indicates From and To must be a Double, which could be basically <Type>Animation where Type could be Int32, Byte, Color etc. From and To are start and end values, Duration is a time (0.5 seconds here) and AutoReverse indicates once it's finished the animation will happen in the other direction. Also set RepeatBehavior="Forever" if you want this animation to continue. By adding a tag under <Storyboard> for <ParellelTimeline>, we can run several animations at once, so we can make the Border and Foreground change color at the same time.
Transform
The last feature I've added to this sample shows a simple ScaleTransform when a button is clicked. We can rotate, skew or scale using <Button.RenderTransform> after the Button tag, and make it dead easy to give our app a 3D feel.
If you want more than one Transform, your next tag should be <TransformGroup> otherwise add the Transformation tag <ScaleTransform ScaleX="1" ScaleY="1.5">, which in this case stretches the height of the control and all children. You can again animate this by using <DoubleAnimation TargetProperty="RenderTransform.ScaleX" From="1" To="-1">, which will take the width from normal to nothing, to normal but with the control backwards.
Note that the control you are animating must have a ScaleTransform tag for this to work.
Example
There is more detail within this example, but I'm hoping this is easily enough to get your feet wet and start thinking about what is possible with XAML. Enjoy:
<Window x:Class="HelloWorld.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Hello World" Height="500" Width="500"
>
<Window.Resources>
<!-- General style -->
<Style x:Key="GrayGradientStyle" >
<Setter Property="Control.Background">
<!-- Set a standard gray vertical gradient style, which will be inherited -->
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="LightGray" Offset="0" />
<GradientStop Color="DarkGray" Offset="0.7" />
<GradientStop Color="Silver" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!-- Glow effect used by next style -->
<OuterGlowBitmapEffect x:Key="OuterGlow" x:Name="OuterGlow" GlowColor="Yellow" GlowSize="0" />
<!-- Style to apply for all buttons, inherits GrayGradientStyle -->
<Style x:Key="{x:Type Button}" BasedOn="{StaticResource GrayGradientStyle}" TargetType="{x:Type Button}" >
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Margin" Value="20" />
<Setter Property="Width" Value="100" />
<Setter Property="BitmapEffect" Value="{StaticResource OuterGlow}" />
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property="Foreground" Value="Red" />
<!-- When IsMouseOver is set to true, set the button to full Opacity and show a Yellow glow around the button -->
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ParallelTimeline>
<DoubleAnimation From="0.5" To="1" Duration="0:0:00.5" Storyboard.TargetProperty="Opacity"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="BitmapEffect.GlowSize" AutoReverse="True" From="0" To="15" Duration="0:0:0.5" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<!-- When IsMouseOver is set back to false, set the button Opacity back to half -->
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="1" To="0.5" Duration="0:0:01" Storyboard.TargetProperty="Opacity"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<!-- Style to apply for the window -->
<Style x:Key="WindowBackground" TargetType="{x:Type Window}">
<Style.Triggers>
<!-- After the form is loaded continually cycle the background colors back and forth between these colors -->
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<ColorAnimation From="LightBlue" To="LightCoral" Storyboard.TargetProperty="Background.Color" Duration="0:0:10" Timeline.DesiredFrameRate="10" AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<!-- Set the style to the above WindowBackground -->
<Window.Style>
<StaticResource ResourceKey="WindowBackground"></StaticResource>
</Window.Style>
<!-- Main controls -->
<StackPanel>
<StackPanel HorizontalAlignment="Center" >
<!-- Hello World Click Me button (automatically picks up Button style) -->
<Button>Click Me
<Button.Triggers>
<!-- When the button is clicked transform the scale of the Hello World border and turn it's opacity to full and back -->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ParallelTimeline>
<DoubleAnimation Storyboard.TargetName="HelloBorder" Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="1" Duration="0:0:5" AutoReverse="True" />
<DoubleAnimation Storyboard.TargetName="HelloBorder" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:5" AutoReverse="True" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
<!-- Hello World box -->
<Border Width="400" Height="300" Name="HelloBorder" BorderBrush="Black" BorderThickness="2" Opacity="0.3" Style="{StaticResource GrayGradientStyle}">
<Border.RenderTransform>
<!-- Will mean Border is invisible due to ScaleX being 0 -->
<ScaleTransform ScaleX="0" ScaleY="1" CenterX="200" />
</Border.RenderTransform>
<TextBlock Width="400" Height="300" Name="HelloText" TextWrapping="Wrap" FontSize="100" TextAlignment="Center">
<TextBlock.Foreground>
<!-- Set a nice radial gradient for the Hello World text -->
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="1" RadiusY="1">
<GradientStop Color="Yellow" Offset="0.2" />
<GradientStop Color="Orange" Offset="0.5" />
<GradientStop Color="Red" Offset="1" />
</RadialGradientBrush>
</TextBlock.Foreground>
Hello World
</TextBlock>
</Border>
</StackPanel>
</StackPanel>
</Window>
Monday, September 18, 2006
Getting started on WPF and .net 3.0 RC1
But for the moment, at RC1, it's probably still a little too risky to fully convert an important machine to Vista, so I'd suggest you get hold of a test machine. Below is some of the software you can use to get you up and running on a test PC, before the .net 3.0 and Vista become official versions.
Vista RC1
I'm very impressed with Vista RC1. It's clearly a "pretty" OS, up there with the latest Mac OS (which I've reluctantly used a bit) and any screenshots I've seen of the fancier Linux OS's. It's features are growing on me, but as a sceptic I'd still say for the vast majority of users there are mild improvements apart from visual ones. With tools like Media Center, DVD authoring, automatic mobile device recognition (eg my PDA) and calender built into the OS, it does avoid a bit of the countless software installs we are used to with a fresh OS, so there is something to be gained from getting Vista.
Go get it now here: http://www.microsoft.com/windowsvista/getready/preview.mspx
Windows Server 2003
Of course if you aren't willing to be a guinea pig for Microsoft, but still want a fresh, legal version of XP for a test machine to try out .net 3.0, Micrsoft is giving out a 6 month trial of Windows server 2003. The beauty of this is you get 6 months uninterupted development on a machine, without Vista complaining that the shipped version is out. You also get a stable fast OS that will run all the .net 3.0 goodness. Not a bad option for a test PC.
Windows Server 2003 180 day trial: http://www.microsoft.com/windowsserver2003/evaluation/trial/default.mspx
Visual Studio trial
Microsoft have of course outdone themselves with the Express editions of Visual Studio. And I'm sure these will include Visual WPF tools later on, but for now WPF programming is best done in Visual Studio from what I've been told.
Again if you don't have this already, Microsoft has 180 day trial for you:
http://msdn.microsoft.com/vstudio/products/trial/
Windows .net 3.0 SDK:
A must for developing applications in .net 3.0 is the SDK itself:
http://www.microsoft.com/downloads/details.aspx?FamilyId=117ECFD3-98AD-4D67-87D2-E95A8407FA86&displaylang=en
Visual Studio Extensions
The extensions for Visual Studio setup all the test projects, so rather than starting with empty projects you can start a new WPF project, which makes life that little bit easier.
The .net 3.0 Visual Studio extensions (RC1):
http://www.microsoft.com/downloads/details.aspx?FamilyId=935AABF9-D1D0-4FC9-B443-877D8EA6EAB8&displaylang=en
WPF
I'm more than interested in WPF than the rest of .net 3.0 at the moment, so here are a couple of tasters that I will be reading over the next few days/weeks also. I'm sure there is way more out there, but for now there is more than enough to get you started. I will be putting my own articles on this blog also, to hopefully go through some of the features in a simplified way.
Here is a nice article with an overview to what WPF is all about. There is no real detail, but it does help to get your head around what XAML will look like, and what WPF can do for you:
http://msdn.microsoft.com/windowsvista/reference/default.aspx?pull=/library/en-us/dnlong/html/introducingwpf.asp
This site gives a good all round look at WPF, with plenty of code samples and tutorials to get you started (click on Download Code... for the files and tutorials):
http://wpf.netfx3.com/
Of course all the other .net 3.0 technologies are here too:
http://www.netfx3.com/default.aspx
And one more link to the mother of information about WPF:
http://windowssdk.msdn.microsoft.com/en-us/library/ms754130.aspx
which can be found in your Windows SDK (hopefully this works on other machines):
ms-help://MS.MSSDK.1033/MS.NETFX30SDK.1033/wpf_conceptual/html/f667bd15-2134-41e9-b4af-5ced6fafab5d.htm
I am due to be looking at a lot of this over the next few weeks and will share my findings. Enjoy!
Tuesday, September 12, 2006
Microsoft AJAX is the new Atlas
It's worth a mention that Atlas is changing it's name and is release date is set to late 2006.
In short the new naming is like this:
"Microsoft AJAX Library" for all Atlas client controls
"ASP.NET 2.0 AJAX Extensions" for the asp.net server side Atlas controls
"ASP.NET AJAX Control Toolkit" for the current Atlas control toolkit
Of course I'm getting all this from the wonderful ScottGu blog article:
http://weblogs.asp.net/scottgu/archive/2006/09/11/_2200_Atlas_2200_-1.0-Naming-and-Roadmap.aspx
Why is it that this naming bugs me? Beta technologies always have the cool and unusual names, whereas the final product is usually so plain and boring.
I can only imagine that searches will be slower and more painful with this new naming. Put "Atlas C#" and other terms into a search engine you will get your results pretty easily. Put "Microsoft AJAX C#" or "ASP.NET AJAX C#" and you may be confused with other AJAX libraries or articles about AJAX as a technology etc. So with this naming we'll need rock solid intellisense and documentation otherwise our lives just got harder.
And to those that haven't followed the Atlas project, it would simply sound like Microsoft found that AJAX was taking off and quickly tacked a library together and and said "Hey, now we have AJAX... see Microsoft AJAX." The truth is the project has been very well thought out. A free client side library, a free asp.net library and a free community built toolkit. It sounds far too open source and cool to be Microsoft. At least too cool to be "Microsoft AJAX"! I see it as one of those projects, along with the wonderful express products, that really reflects Microsofts future potential as a helping hand to programmers, not an evil dictatorship set to make everyone learn the hard way to code with the highest money outlay.
Oh well, it's only a name in the end, the technology is still cool and I'd still tip it to be the number 1 AJAX library for .net shortly after it's release. Lets hope Scott and the others keep pushing the technology to great heights.
Tuesday, September 05, 2006
C# object arrays BinarySearch, Sort and IComparer
This isn't so much a new or very difficult thing, but it's something I've happened to come across twice recently, and I've needed to dig up the example code both times, so thought I'd add it to my blog for future reference.
Basically, I'm getting much more interested in dealing with object arrays rather than DataSets even in smaller projects. I feel like I have more control over certain things with object arrays, like business logic and customising properties. Now one of my projects was .net 2.0 so I used the generic List<> which was quite nicely put together, but my other project is a 1.1 project, so needed a slightly more outdated method.
I'll explain that one here, and probably add a note about the List<> way to do the same (plus more) next time.
Setting up the object array
For a very basic example I've got a class with a couple of fields in it for an Mp3 list:
public class Mp3Class {
private string _Artist;
private string _Song;
private int _Ranking;
public string Artist { get { return _Artist;} set {_Artist = value;}}
public string Song { get { return _Song;} set {_Song = value;}}
public int Ranking { get { return _Ranking;} set {_Ranking = value;}}
public Mp3Class (string Artist, string Song, int Ranking)
{
_Artist = Artist; _Song = Song; _Ranking = Ranking;
}
}
A basic example to get some data into this would be:
Mp3Class[] mp3s = new Mp3Class[5];
mp3s[0] = new Mp3Class("Cave", "Ship Song", 9);
mp3s[1] = new Mp3Class("Nirvana", "Smells like teen spirit", 3);
mp3s[2] = new Mp3Class("Sonic Youth", "100%", 1);
mp3s[3] = new Mp3Class("Cave", "Red right hand", 4);
mp3s[4] = new Mp3Class("Nirvana", "Heart shaped box", 7);
The Array class
So the thing you really need to get your head around working with arrays of objects is the Array class. It's very similar to working with List<>, but missing a few features. For simple arrays, things like IndexOf, Sort and even BinarySearch can be straight forward, but with object arrays a little more work is needed, but fortunately not too much.
Array.Sort
For sorting our class, there is one big thing that makes it more difficult. Which property do you sort on? In this case all are valid, as you may be ordering by artist, by ranking or even by song, but that means we need to implement another class to help us out. The IComparer interface gives us the ability to sort things how we wish using our objects. Basically, if we want to sort this list by Artist, we can implement an IComparer class which compares the Artist string, and Sort will do the rest, or if we want to sort by Ranking, we can compare the ranking numbers and Sort will do the rest. Here are those two examples:
public class ArtistCompareClass : IComparer
{
int IComparer.Compare(object x, object y)
{
int RetVal = String.Compare((x as Mp3Class).Artist, (y as Mp3Class).Artist, true);
return RetVal;
}
}
public class RankingCompareClass : IComparer
{
int IComparer.Compare(object x, object y)
{
int RetVal = (x as Mp3Class).Ranking - (x as Mp3Class).Ranking;
return RetVal;
}
}
The ArtistCompareClass cheats by using String.Compare (with case insensitivity). IComparer.Compare is simply looking for a negative if the first object should be ordered earlier, 0 if they are the same and a positive number if the 2nd object should be ordered earlier. Passing this object to Array.Sort will sort the array alphabetically by Artist.
The RankingCompareClass implements the same IComparer.Compare, so again, if the first Ranking is smaller it returns a negative, if they are the same a 0, if the 2nd Ranking is smaller a positive. This will order the object array by Ranking.
The call to sort the array will look like this:
Array.Sort(mp3s, new RankingCompareClass());
You now have the mp3s ordered by Ranking.
Array.BinarySearch
The BinarySearch as the name suggests searches the array using the same IComparer (or at least can do it this way). So again IComparer helps us search through an array of objects, when the language would otherwise have no idea of what it's searching for.
Note: Remember these key things when using a BinarySearch:
- You must sort by the IComparer before using BinarySearch
- It won't work (100%) if your "key" is not unique
- If the result is negative, you can do a bitwise operation to see the closest match
- If you are only searching a subset of the array, it will still return the item in the entire array that's a match.
Here are a couple of examples. I'll give you another IComparer which will help do "real" searches easier. In this case we'll send through the ranking as the 2nd parameter rather than a full object. As you can imagine if someone wanted to search for the song with ranking number 5, it's easier to pass through 5 than new Mp3Class("", "", 5):
public class RankingCompareValueClass : IComparer
{
int IComparer.Compare(object x, object y)
{
int RetVal = (x as Mp3Class).Ranking - (int)y;
return RetVal;
}
}
To find the object which matches a search with a ranking of 4 (MatchingObject is 2, which is the 3rd object in the array):
Array.Sort(mp3s, new RankingCompareClass());
int MatchingObject = Array.BinarySearch(mp3s, 5, new RankingCompareValueClass());
MessageBox.Show(mp3s[MatchingObject].Artist + " - " + mp3s[MatchingObject].Song);
If the user tried to search for a ranking of 5, we could take them to the next closest match (MatchingObject is 3, which is the 4th object in the array):
Array.Sort(mp3s, new RankingCompareClass());
int MatchingObject = Array.BinarySearch(mp3s, 5, new RankingCompareValueClass());
if (MatchingObject < matchingobject =" ~MatchingObject;">" - " + mp3s[MatchingObject].Song);
That's about it. It's worth pointing out that List<> does most of this stuff plus more, and is slightly easier to use, so I'd tend to use that for any 2.0+ projects.
Tuesday, August 29, 2006
Atlas HoverMenuExtender example
What is it?
The Atlas HoverMenuExtender gives you a way to easily add a panel with extra content to a control, without clutteruing up the screen. You can bind all the data in your grid, while at the same time binding your hover menu panel, therefore keeping all you code in one simple place but adding nice functionality.
Pros?
- Clean up your interface by only showing key data, and showing extra data on hover
- Have a fast way to show master/detail data
- Hide all your extra command buttons in a GridView
Cons?
- For a first time user of your site, it may not be that obvious that extra data is available on mouse over
- It may also be annoying that menus keep popping up whenever scrolling past a grid
- Must set the visibility to hidden in the stylesheet to make sure the panel doesn't show quickly when the page is loading
- As a note I had a slight hitch when trying this extender in a real situation, in that nothing showed. Funnily enough it worked in Firefox though, and it turned out that an "overflow:auto" (ie HTML scroll bar) in another control on that form caused the issue
- PopDelay says how long to leave the popup there, whereas I would have though it would indicate how long to wait before showing it.
I feel there are a couple of tricks to the trade here, and some of these apply to other Atlas extenders also:
- In my example, having width="100%" on the GridRowPanel (panel shown in grid before popup) means the popup will appear anywhere on the grid, otherwise it will only appear when hovering over the actual content. Another way to fix this is have a background color. Also this works as I would have expected in Firefox, just not IE.
- The popup window must be hidden by default, otherwise you will notice the control breifly while the page loads. Atlas will make it visible again when it needs to. Do this with Visibility:hidden in the stylesheet or add style="display:none"
- The HoveMenuExtender MUST be placed in the ItemTemplate/EditTemplate etc for a GridView. This is because the target control is internal to that template, and therefore isn't visible to controls outside the grid.
- Certainly on a grid PopDelay should be short to avoid ugly or unreadable popups for other rows.
Example
In this example, I'd like to show a few extra fields in a GridView when hovering over a row with the mouse.
- Add an Atlas ScriptManager to the form
- Setup a GridView with an ItemTemplate with many columns
- Add the databinding code how you wish to your data.
- In the ItemTemplate have one panel for the columns you want to show and one for the columns you want to have as the hover panel
- Make sure the hover panel has Visibility:hidden in the style or style="display:none" in the panel tag
- Add a HoverMenuExtender inside the ItemTemplate
- Set the TargetControlID to the panel you want to permanently display on the grid.
- Set the PopupControlID to the panel you want to show when the mouse hovers over the grid
- Finally set a HoverCssClass for how you want the main grid row to look when hovered over
- PopupPosition dictates on which edge of the TargetControlID you want the popup to appear
- OffsetX, OffsetY say how far down and right to place the popup from PopupPosition.
- PopDelay means how long the popup will show once the mouse leaves the control. Set this to a low amount on grids.
<%@ Page Language="C#" %>
<%@ Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="cc1" %>
<%@ Import Namespace="System.Collections.Generic" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public class Mp3Class
{
private int _Mp3Number;
private string _Artist;
private string _SongTitle;
private decimal _Rating;
public int Mp3Number { get { return _Mp3Number; } set { _Mp3Number = value; } }
public string Artist { get { return _Artist; } set { _Artist = value; } }
public string SongTitle { get { return _SongTitle; } set { _SongTitle = value; } }
public decimal Rating { get { return _Rating; } set { _Rating = value; } }
public Mp3Class(int Mp3Number, string Artist, string SongTitle, decimal Rating)
{
this.Mp3Number = Mp3Number;
this.Artist = Artist;
this.SongTitle = SongTitle;
this.Rating = Rating;
}
}
protected void Page_Load(object sender, EventArgs e)
{
List<Mp3Class> Mp3List = new List<Mp3Class>();
Mp3List.Add(new Mp3Class(1, "Bernard Fanning", "Wish You Well", 8));
Mp3List.Add(new Mp3Class(2, "Ben Lee", "Catch My Disease", 7));
Mp3List.Add(new Mp3Class(3, "Gorillaz", "Feel Good Inc.", 9));
Mp3List.Add(new Mp3Class(4, "Foo Fighters", "Best Of You", 6));
Mp3List.Add(new Mp3Class(5, "Gorillaz", "Dare", 9));
TopFiveList.DataSource = Mp3List;
TopFiveList.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Atlas HoverMenuExtender</title>
<style type="text/css">
.popupMenu {background-color:Silver;position:absolute;visibility:hidden;border-width:1px;border-style:solid;border-color:Black;}
.popupHover {background-color:Gray;
</style>
</head>
<body>
<atlas:ScriptManager ID="scriptmgr" runat="server"></atlas:ScriptManager>
<form id="form1" runat="server">
<h2>Top 5 Mp3's</h2>
<div>
<asp:GridView ID="TopFiveList" ShowHeader="false" GridLines="Both" Width="200px" AutoGenerateColumns="False" runat="server">
<Columns>
<asp:BoundField Visible="false" DataField="Mp3Number" />
<asp:TemplateField>
<ItemTemplate>
<asp:Panel ID="HoverPnl" CssClass="popupMenu" Width="300px" runat="server" style="display:none">
<table>
<tr>
<td>
<b>Artist</b></td>
<td>
<asp:Label ID="ArtistLbl" Text='<%# Eval("Artist") %>' runat="server"></asp:Label></td>
</tr>
<tr>
<td>
<b>Song Title</b></td>
<td>
<asp:Label ID="Label1" Text='<%# Eval("SongTitle") %>' runat="server"></asp:Label></td>
</tr>
<tr>
<td>
<b>Song Rating</b></td>
<td>
<asp:Label ID="Label2" Text='<%# Eval("Rating") %>' runat="server"></asp:Label></td>
</tr>
</table>
</asp:Panel>
<asp:Panel ID="GridRowPnl" Width="100%" runat="server">
<asp:Label ID="Label3" Text='<%# Eval("SongTitle") %>' runat="server"></asp:Label>
</asp:Panel>
<cc1:HoverMenuExtender ID="HoverMenuExtender1" runat="server">
<cc1:HoverMenuProperties PopupPosition="right" HoverCssClass="popupHover" PopupControlID="HoverPnl"
TargetControlID="GridRowPnl" PopDelay="50" />
</cc1:HoverMenuExtender>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
Tuesday, August 22, 2006
Atlas Extender with code behind
What is it?
An extender is the same as my previous blog, but in this case it's linking the controls to the extender using server side or code behind code. Without this ability, we'd be stuck with Atlas effects on only the controls you can design.
How does it help me?
It will only help if you need to add controls dynamically. Where you can I'd still suggest to put the properties on the form itself like previously explained.
Pros?
- Gives you the ability to add controls dynamically and still give them Atlas behaviors
Cons?
- Extender properties can't be added after the page init procedures. Eg a button click happens after a page init, therefore you can't add extender properties in a button click.
- You must add the dynamic controls to the form before finalising your extender properties. So if the code is adding a lot of controls to a panel, you must wait until the panel is added to the form before adding the extender properties.
- Potentially adds more difficultly to debugging.
Example
Another simple example here with an Atlas DragPanelExtender. No controls on the aspx form, and one control added dynamically to the DragPanelExtender.
- Add an atlas ScriptManager to a webform.
- Drag an atlas DragPanelExtender onto the form.
- Double click on the form to create a Page_Load method in your code behind.
- In the code behind dynamically add a panel, another panel within that panel to be the drag panel, and another control to be the content inside the main panel.
- Add these to the form.
- Now create a DragPanelProperties object and set the TargetControlID to the main panel and the DragHandleID to the header panel which is to be the draggable control.
- Link this to the control to the extender by adding the object to the TargetProperties collection.
- All done, the dynamic control will now appear with the Atlas effects also.
Full Code:
<%@ Page Language="C#" %>
<%@ Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="cc1" %>
<!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)
{
if (!IsPostBack)
{
BuildPageDynamically();
}
}
private void BuildPageDynamically()
{
// One of 3 main panels.
Panel p = new Panel();
p.Height = 200;
p.Width = 200;
p.ID = "Panel1";
p.BorderWidth = 1;
p.BackColor = System.Drawing.Color.PaleVioletRed;
// Add a header panel to drag by.
Panel HeaderPanel = new Panel();
HeaderPanel.Height = 20;
HeaderPanel.Width = 200;
HeaderPanel.ID = "HeaderPanel1";
HeaderPanel.BorderWidth = 1;
HeaderPanel.BackColor = System.Drawing.Color.PapayaWhip;
p.Controls.Add(HeaderPanel);
// Add a label in the main panel.
Label l = new Label();
l.Text = "Drag me";
l.Width = 200;
p.Controls.Add(l);
// Add the main panel onto the main form
this.Controls.Add(p);
// Create a new properties for the extender.
DragPanelProperties dpp = new DragPanelProperties();
dpp.TargetControlID = p.ID;
dpp.DragHandleID = HeaderPanel.ID;
// Add the properties to the extender
DragPanelExtender1.TargetProperties.Add(dpp);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Atlas Extender Code Behind</title>
<atlas:ScriptManager ID="scriptmgr" runat= "server" />
</head>
<body>
<form id="form1" runat="server">
<cc1:DragPanelExtender ID="DragPanelExtender1" runat="server">
</cc1:DragPanelExtender>
</form>
</body>
</html>