MIX10 Recap

Not only did I have the chance to attend my first PDC recently, but my gracious employer sent me to MIX10 this year. I’ve always wanted to go to this conference as I have design interests and tendencies and this is place where conversations about design happen in conjunction with the Microsoft technology stack.

Here is my personal recap of the event. I did this for PDC09 and it was quite helpful to not only reflect back on the conference but also in compiling a list of sessions that I wanted to watch offline (or rewatch again).

The main excitement was, of course, Windows Phone 7. However, my main objective at the conference was to hit up a lot of the sessions on design, learning more about it myself, and how I can better change my own personal development process as well Starkey’s development process. With that in mind, and especially because he is doing some iPhone development, my colleague picked up the Windows Phone sessions. I’m definitely going to dive in on some of those now that the conference is finished.

The best part of the conference was probably just meeting and hooking up (for the first time) with some of the other WPF Disciples. You can always take in the conference offline (and often in a better manner), but it isn’t every day where you can talk with (and have fun with) great minds and people.

It was an excellent conference! I hope I will soon be able to attend again.

Sessions That I Attended

Session Code Session Title Presenters Notes
WKSP02 Design Fundamentals for Developers Robby Ingebretsen This workshop and Robby’s other session (which was kind of a follow-up to the workshop) were the highlights of conference for me. He is a designer that has a background in development and was part of the team that made WPF. He has done some beautiful and amazing work. A recent piece of work is his design efforts on Seesmic for Windows (which has been converted from WPF to Silverlight recently). He is also the creator of one of my favorite tools: Kaxaml. Besides the cool name, it is the best loose xaml split-view editor out there. The session was all about introducing design to people who don’t have a background in design. As this was a pre-conference workshop, it probably won’t be released as a video you can watch offline. However, Robby also did this session last year, and for some reason they did release it for MIX09. A must watch.
WKSP03 Design Tools & Techniques Arturo Toledo, Guido & Luigi Rosso, Corrina Black I was very excited for this session because Arturo is a designer PM for Microsoft. Last year he published a great series on UI Design for Developers. Unfortunately, they changed things around and he was not the one presenting but the content was still top-notch. A set of twins, one a developer (Luigi) and one a designer (Guido), presented for the first two hours. They talked about the design and development process for their company, Archetype. They also showed off some amazing experiences they’ve created and then how to do create those experiences in Expression Blend. One of those applications was a Windows Phone 7 news reader that was jaw-dropping (and demoed in the keynote) and it was obvious that they get and totally understand the designer/developer collaboration/workflow. I encouraged them to blog about this because I think a lot of people could learn from them. Finally, Corrina Black finished off the third hour with a high-level Windows Phone 7 design overview. As before, since this was a workshop, the video will likely not be posted … which is too bad. Definitely worth a watch, if it becomes available.
KEY01 Keynote Day 1 Scott Guthrie, Joe Belfiore This keynote was all about Windows Phone 7 where Joe covered what it was about and Scott Guthrie covered the development tools (Visual Studio 2010) and technology (Silverlight, XNA) for the phone. The only disappointment was that they didn’t hand out a phone for us to start playing with. PDC really set the bar high for swag (they gave us a free netbook at that conference). I really, really like that I’m already a Windows Phone 7 developer due to my WPF and Silverlight skills.
DS11 Great User Experiences: Seamlessly Blending Technology & Design Andy Hood This was a session by Andy Hood of AKQA. He leads a creative development team there and ran through four AKQA gigs where they blended (think: no rough edges) technology with great design. My favorite was how they used Photosynth in a Facebook Connect game called 221B (that is associated with the Sherlock Holmes movie). They also went to great lengths to remove the Facebook branding and from what they showed, you couldn’t tell it was associated with Facebook at all. Favorite quote: “Beware the lollipop of mediocrity, lick it once and you will suck forever.”
EX14 Understanding the Model-View-ViewModel Pattern Laurent Bugnion Here is another session that I was greatly looking forward to and I wasn’t disappointed. Laurent is a fellow WPF Disciple and his session was an Open Call session that was voted in by the people planning on attending MIX. That is something in and of itself. He covered what the pattern is and what the pattern is not with a special emphasis on how to keep things blendable (i.e. how to use MVVM and still be able to use the design surface in Blend). If you know me, you know that is right up my alley! He also went over what is contained in his MVVM Light Toolkit. Laurent in a word, rocks. Definitely a must watch.
EX06 10 Ways to Attack a Design Problem and Come Out Winning Robby Ingebretsen I’ve already mentioned (above) that this session along with the workshop were my favorites. This session was more practical, more of the how, and less of the theory of design. In particular, he went through and gave the audience 10 design attack moves. My favorite was number 5 which was: Learn Technique. And, as an example, he showed off several techniques that he uses in Photoshop … a couple of which use blend modes. Ah, now, you see why it was my favorite! I just so happened to have created a blend mode library for WPF & Silverlight (see here and here). I really liked number 4 too which was: Sketch Early and Often. I don’t even have to say this: definitely a must watch.
KEY02 Keynote Day 2 Scott Guthrie, Dean Hachamovitch, Bill Buxton, Doug Purdy This keynote was focused on Internet Explorer 9, design, and OData (a web protocol for querying and updating data on the web). Dean Hachamovitch talked about what’s new in IE9 and I was particularly impressed with the continued trend in taking advantage of hardware acceleration and your system’s GPU. Doug Purdy talked about OData and Bill Buxton talked design with an emphasis on what it really means to design for natural experiences.
DS06 Touch in Public: Multi-touch Interaction Design for Kiosks & Architectural Experiences Jason Brush Jason Brush from Schematic gave this presentation and it was focused on design of touch user experiences in a public setting, e.g. like kiosks or large screen wall type experiences. After recently getting an iPod Touch, I’ve become very interested in natural user interfaces (NUI) and it is quite fascinating (and obvious I guess) that you need to design differently for each of theses experiences. The basic message: design for the space that you will be in. Don’t forget the context of your application.
DS08 Creating Great Experiences Through Collaboration Noah Gedrich, Eric Perez, Sean Scott This session was presented by a trio of people from Blitz: a developer, a creative, and a user experience guy and its focus was how collaboration between all the disciplines can yield some amazing experiences. They talked about collaborating early and often and the mutual respect between disciplines required to make that happen. They also shared some of the practical methodology that Blitz uses, including how they brainstorm as a team. Another interesting thing they brought up was how they use the 6 human needs (significance, connection, certainty, variety, growth, and contribution) in order to craft immersive experiences.
DS12 Total Experience: A Design Methodology for Agencies Conor Brady This session was presented by an Irish fellow named Conor Brady of Organic. In it, he talked about Organic’s creative process and how they navigate the complex world of technology. One of the key things I was trying to get out of MIX personally was how other companies go about creating experiences and how they blend design and development in doing so … and so this session was right up my alley. Conor really knew his stuff and the experiences he shared were very cool, but it was a little too high level for my taste.
DS16 An Hour with Bill Buxton Bill Buxton If you’ve never listened to Bill Buxton, you have to check this session out. He keynoted both last year and this year and is one of the most interesting people I’ve ever listened to. An influential designer on the world stage, he is also a principal researcher at Microsoft that is changing the company from within. He has a very engaging style: it is very laid-back and it’s like you’re talking to a friend or colleague. He was very keen on what he called BXT. BXT stands for Business, Experience, and Technology and he maintained that every team must have this trio of expertise and that they each must be on the same footing.
EX25 Design the Ordinary, Like the Fixie DL Byron, Kevin Tamura Yet another design/UX session that I attended. The main message here was of minimalism. Good design is hard, but it makes the complex … simple. That is, it is all about taking away. Once you can’t take anything else away, you’ve nailed it. This is a good message to internalize as a software developer for in my experience it is all too easy to keep cluttering up that user interface and creating a behemoth that scares (especially new) users and intimidates them.
EX18 Developing Natural User Interfaces with Microsoft Silverlight & WPF 4 Touch Joshua Blake This was another Open Call session voted in by the community and it didn’t disappoint. It was focused on the practicalities of how to create natural user interfaces (NUI) with multi-touch and using Silverlight and WPF 4. In fact, he even gave his presentation using some software that he created (that he called Natural Show). Definitely one of the better session at the conference.
CL03 Prototyping Rich Microsoft Silverlight Applications with Expression SketchFlow Chris Bernard In this session, Chris Bernard, a UX Evangelist at Microsoft went over how to use SketchFlow in order collaboratively sketch, prototype, and explore the user experience you are trying to create. This was a nitty-gritty session that personally exposed me to more of SketchFlow’s functionality. Chris did an amazing job and made several interesting claims about how useful SketchFlow is. The one that stands out is that he says that you should always be able to sketch up an animation faster in SketchFlow than doing it in code or xaml. He also said that you should start with SketchFlow animation before you use Blend behaviors. Great session and worth your time especially if you are new to SketchFlow like I am.

Sessions That I Missed but Want to Watch

Session Code Session Title Presenters Category
CL02 Authoring for Windows Phone, Silverlight 4 and WPF 4 with Expression Blend Christian Schormann, Peter Blois Blend
CL55 Dynamic Layout & Transitions for Microsoft Silverlight 4 with Microsoft Expression Blend Kenny Young Blend
       
EX15 Build Your Own MVVM Framework Rob Eisenberg MVVM
CL52 Microsoft Silverlight Optimization & Extensibility with MEF Glenn Block MEF
       
DS03 Running with Wireframes: Taking Information Architecture (IA) into Design Matt Brown UX/Design
EX26 From Comp to Code: A Design Communion Evan Sharp UX/Design
DS04 The Life Cycle of a Wireframe Nick Finck UX/Design
DS13 The Elephant in the Room Nishant Kothary UX/Design
DC01 The Laws of User Experience Anthony Franco UX/Design

Above are the ones I most want to watch, but I’ll definitely want to take in some of the Windows Phone 7 ones as well as some of the Silverlight ones. So, here those are (for easy access for myself and others).

Other Interesting Sessions

Session Code Session Title Presenters Category
CL13 Overview of the Windows Phone 7 Series Application Platform Charlie Kindel WP7
CL14 Windows Phone UI & Design Language Chad Roberts, Michael Smuga, Albert Shum WP7
CL16 Building Windows Phone Applications with Silverlight, Part 1 Mike Harsh WP7
CL17 Building Windows Phone Applications with Silverlight, Part 2 Peter Torr WP7
CL18 Windows Phone Application Platform Architecture Istvan Cseri WP7
CL60 Silverlight Performance on Windows Phone Seema Ramchandani WP7
CL19 Development & Debugging Tools for Building XNA Games for Windows Phone Cullen Waters WP7
CL22 Building a High Performance 3D Game for Windows Phone Shawn Hargreaves, Tomas Vykruta WP7
       
EX30 SVG: The Past, Present, and Future of Vector Graphics for the Web Patrick Dengler, Doug Schepers Graphics
       
CL56 A Case Study: Rapid WordPress Design & Prototyping with Expression Web 3 Morten Rand-Hendriksen WordPress
       
EX21 Syncing Audio, Video, and Animations in Microsoft Silverlight Applications Dan Wahlin Silverlight
CL07 Microsoft Silverlight 4 Overview: What’s in Store for Silverlight 4? Keith Smith Silverlight
CL10 Stepping Outside the Browser with Microsoft Silverlight 4 Ashish Shetty Silverlight
CL15 An Introduction to Developing Applications for Microsoft Silverlight Shawn Oster Silverlight
CL08 Microsoft Silverlight 4 Business Applications Scott Morrison Silverlight
CL59 Unit Testing Silverlight & Windows Phone Applications Jeff Wilcox Silverlight
EX07 Principles of Microsoft Silverlight Graphics & Animation Jeff Paries Silverlight
EX31 Developing Multiplayer Games with Microsoft Silverlight 4 Mike Downey, Grant Skinner Silverlight
EX38 Building Large-scale, Data Centric Applications with Silverlight Roman Rubin, Ramya Parthasarathy Silverlight
CL53 Flash Skills Applied to Microsoft Silverlight Design & Development Adam Kinney Silverlight
EX54 An Enterprise Perspective on Silverlight 4 Robert Ellis Silverlight
EX51 Building Finance Applications with Microsoft Silverlight 4 Cai Junyi Silverlight
CL50 Search Engine Optimization for Microsoft Silverlight Brad Abrams Silverlight
       
CL30 Building Innovative Windows Client Software Scott Hanselman, Tim Huckaby, Tim Sneath, Scott Stanfield, Dave Wolf UX/Design
DS05 Total Experience Design Paul Dawson UX/Design
EX56 Designing Rich Experiences for Data Centric Applications Yoshihiro Saito, Ken Azuma UX/Design
FTL02 Building Pivot Collections Troy Schauls, Jeff Weir UX/Design

Heh. This recap got longer than (and took more work) I thought it would. Hope it is useful and helpful to others.

Enjoy!

Share

Snoop: Now Supports WPF 4.0

This is just a quick post to point people to the fact that I have updated Snoop on CodePlex (http://snoopwpf.codeplex.com/) such that it now supports WPF 4.0.

If you try to Snoop a WPF 4.0 application with the WPF 3.5 version, you will get the following error message:

SnoopError

I speculate that this is because there is a brand new CLR with .NET 4.0 (WPF 4.0) applications. Yes, that’s right, a brand new CLR. We haven’t had one of those for a while.

If someone can confirm this or provide a better understanding of why I can’t Snoop WPF 4.0 applications without retargeting Snoop to .NET 4.0 … please shed some light for me.

So, there are now 4, count them, 4 versions of Snoop:

  1. Snoop 32-bit for WPF 3.5
  2. Snoop 64-bit for WPF 3.5
  3. Snoop 32-bit for WPF 4.0
  4. Snoop 64-bit for WPF 4.0
    You need to use the right version of Snoop in each particular situation … otherwise … thar will be problems, matey!

I have also added another label to the app chooser so that you know which version you currently have up. Take a look … this is what it looks like for the 64-bit/WPF 4.0 version:

image

Let me know if you have any problems by creating a discussion (or participating in a current one) on the http://snoopwpf.codeplex.com site.

Enjoy and happy Snooping! 🙂

Share

Snoop: Now on CodePlex

CP_banner_111x111_gen 

Snoop is now on CodePlex at snoopwpf.codeplex.com

The community reception to my efforts (blog posts: 1, 2, 3) on Snoop have been wonderful. Some like Anvaka have offered additional feature suggestions; others have just encouraged me.

In my last post, a fellow commented asking why it wasn’t up on CodePlex. Well, this was a great suggestion and one that I had actually already considered. That prompted me to email Pete Blois (the original author) for his permission. He graciously gave it and so I then proceeded to put it up there.

It took me a little while, but I now have the initial bits uploaded … that is, the same stuff that is available here at my blog.

Now, there are a bunch of things on the todo list. Most notably, I’ve already modified Snoop so that it works for WPF 4.0 … and definitely want to share that with the world.

So, please be patient, I’ll get to it. Those silly day jobs! 😀

Some Info

If you are going to download the source code and build it, some comments are in order (I’ll put this out at the CodePlex site too).

There are (go to Build->Configuration Manager) 3 solution platforms (x86, x64, Any CPU) and 2 solution configurations (Debug, Release). The x86 platform is for 32-bit, the x64 platform is obviously for 64-bit, but … what is Any CPU?

Well, Any CPU is only around for Blendability. That is, for some odd reason, I couldn’t bring up the Blend designer Snoop’s window unless it was in this configuration. I have intentionally marked the ManagedInjector project to not be built under the Any CPU configuration. Since Any CPU will run as 32-bit on 32-bit operating systems and as 64-bit on 64-bit operating systems, using Any CPU will likely cause a mismatch (and a headache :)) with the ManagedInjector dll.  The project which builds the ManagedInjector.dll is a C++ project and there isn’t an Any CPU setting for those (they can only be specifically built to Win32 or x64).

Or, in other words, make sure you switch into another platform, before you build or the build will fail.

Here’s a chart for quick reference:

Platform Configuration Notes
x86 Debug For 32-bit.
x86 Release For 32-bit, builds the installer.
x64 Debug For 64-bit.
x64 Release For 64-bit, builds the installer.
Any CPU Debug, Release Only for Blendability. Do not use.

 

Call to Action

If you have a feature request or want to be involved somehow (maybe as a contributor), please don’t hesitate to contact me.

For near future though, I’m going to keep the project closed until I can change the copyright info to Ms-PL and clean up the code a bit.

Thanks

Finally, I want to publicly thank Pete Blois for first creating this awesome tool and for giving us the permission to get it going on CodePlex. A big thanks Pete!

Share

Snoop: Now with 64-bit Support and More

The other day I was rebuilding an application such that it would specifically target the x86 platform … solely because I wanted to Snoop it.

I’ve done this many, many times because it is the only way I’ve been able to Snoop applications on my Windows 7 64-bit operating system. And, I thought, “Boy, this is stupid. I should be able to build a 64-bit version of Snoop such that I don’t have to do this anymore.”

And that is exactly what I did.

Now … presenting Snoop 32-bit!

image

And Snoop 64-bit!

image

Here are the binaries for the 32-bit version and here are the binaries for the 64-bit version.

(The binaries are now (see posts: 1, 2) up on CodePlex. Please go download it from there as those binaries will contain the latest and greatest bits.)

It was rather a simple matter really. I just needed to change all the project configurations so that they targeted the x64 platform … for the x64 version of Snoop … and all the project configurations so that they targeted the x86 platform … for the x86 version of Snoop.

This was so easy and worked so nicely … that I searched the internet to see if anyone had done this already … and I found Dan Hanan’s nice post on the matter.

The problem, though, was that he did it for original version of Snoop … and not the nicely styled and improved version that Pete Blois currently is making available since property editing was originally (still?) broken in that version. However, he also had several nice usability features that I was drooling over and wanted for my very own. 😀 And I, of course, have already fixed the property editing issue in my version (see previous posts: 1, 2) with a little help from Mark Kharitonov (see this forum post for more info on that).

So, I emailed him, got his permission to integrate those changes, and promptly did so. I also added a few improvements myself.

The Improvements

Here is what has been improved (over and above Pete Blois’ current version):

Improvement Originator
Handles WPF interop scenarios (both Windows Forms hosting WPF and WPF hosting Windows Forms). Cory Plotts
Fixed the ability to edit properties. Mark Kharitonov
Modified Snoop so that it can handle visual trees that have nesting greater than 255 levels deep. Mark Kharitonov
Modified the project configurations so that you can build a 32-bit version and a 64-bit version. This is what the blog post is all about! Ha! Cory Plotts
Dan Hanan
Turned off the showing of properties at their default value (by untoggling the Show Defaults toggle button). Dan Hanan
Turned auto refresh off in the AppChooser. Snoop was previously polling every 20 seconds for new applications. Dan Hanan
Added a checkbox to turn auto refresh back on (if you so desire). Dan Hanan
Added a label to the AppChooser to indicate 32-bit versus 64-bit. Dan Hanan
Added a wait cursor when the AppChooser is busy iterating over the applications to possibly Snoop. Dan Hanan
Added the capability to bring the selected tree view item into view. Dan Hanan
Added the capability to filter properties based on predefined sets of properties. Dan Hanan
Added the ability to pop the target (after a delve) with the back button on the mouse. Dan Hanan
Modified the selected item in the tree view to be a light blue even when it doesn’t have focus. Dan Hanan
Added the ability to pop the target (after a delve) with the alt-left arrow keyboard sequence. Cory Plotts
Added the ability to remember window position, size, and the maximized/minimized/normal state for all three Snoop windows. Cory Plotts
Removed the filtering of ‘devenv’ out from the list of applications that you can Snoop. Cory Plotts
Modified the project configurations so that it never builds the installer. I just copy the Snoop executable and the ManagedInjector dll from place to place. Don’t know if this an improvement. 🙂 Cory Plotts
Fixed the x86 installer and created an installer for x64. Snoop is no longer being added to the GAC and the assemblies are thus no longer strong named. The installers for both platforms should now work. Cory Plotts
Integrated Anvaka’s great suggestion below (see the comments). That is, I moved the long label that tells a user how to ctrl-shift click on the application being Snoop(ed) (to a tool tip on the tree view) … and replaced it with a label that tells the user what the immediate following hyperlink is … that is, the Keyboard.FocusedElement. Also added another label and hyperlink for the current selection’s focus scope. Andrei Kashcha (Anvaka)

I chose not to integrate a couple of Dan Hanan’s changes. First, I did not integrate the ‘indexer delve’. Well, actually I did, but then noticed that Pete Blois’ new version already allowed you to delve into items in a collection … and so I backed it out.

Second, I did not integrate the ‘use 2nd monitor if present’ feature. I liked that feature but thought that I would try to improve upon it by remembering the position and size of all the windows … regardless of the number of monitors. So, with a little help from this StackOverflow question and this MSDN sample … that is what I did. It seems to work nicely. Let me know if you have any problems with it.

Snoop(ing) Visual Studio 2010

Finally, ever since I’ve installed Visual Studio 2010, I’ve wanted to take a peek under the covers with Snoop (remember … Microsoft used WPF in this latest version of Visual Studio). I originally thought I couldn’t Snoop it … because it was running as a 64-bit application and I only had a 32-bit version of Snoop.

So, when I got the 64-bit version of Snoop going, I quickly tried Snooping Visual Studio 2010. No luck! Bringing up task manager, I quickly remembered that Visual Studio runs as a 32-bit application on 64-bit operating systems. See this post by Rico Mariani for more info.

As I have recently been invited into the WPF Disciples group, I posed the question there. Imagine my surprise to find out that devenv.exe was manually being filtered out (since Visual Studio 2008 would load WPF assemblies … but Snoop would fail since Visual Studio 2008 wasn’t built with WPF).

That gave me quite the chuckle. Or, more like, duh! So, promptly removed that and Snoop(ed) Visual Studio 2010 to my delight (check out the red Snoop adorner):

image

And, of course, the Snoop AppChooser:

image

And, finally, the main Snoop user interface:

image

I think that is so cool. Ok, I know … I need mental help. 😀

The Source Code

In the past, I have not released the source code since I have wanted to get Pete’s permission before I do so. I actually met him at PDC 2009 this year. I brought up the fact that I had modified Snoop to handle interop scenarios … but I forgot to ask him about the source code!

There are so many changes now … that I think it would be counter-productive to not release it … in case someone else wants to take Snoop even further than I (and Dan and Mark) have. If you do modify it … and take it further … please let me know! I would love the chance to determine whether to integrate the changes into this version.

So, here it is: the source code.

(The source code is now (see posts: 1, 2) up on CodePlex. Please go download it from there as that code will contain the latest and greatest bits.)

Enjoy!

p.s. If you were one of the few who pulled down the binaries immediately after I posted it, then you may not have gotten the Snoop.exe.config file. Unfortunately, in this case, Snoop does not seem to close down all the way (i.e. I had to manually kill it through task manager). You’ll want to get the latest binaries that do include the Snoop.exe.config file … or manually rebuild them yourself with the source code.

An Update

See above (in the table of improvements), but I fixed the installers and integrated a nice idea by Anvaka. All the attached binaries (which should be installers now) and source code have been updated.

Share

Blend Modes: Hue, Saturation, Color, and Luminosity with WPF 4.0

I’ve been toying with and working on this blend mode library of mine for some time now (see posts 1, 2, 3, 4, 5). However, it is now only with WPF 4.0 (currently Beta 2) … that I can actually implement all the blend modes.

Hue, Saturation, Color, and Luminosity: Where Are You?

If you were watching closely, you will have noticed that I have not (to date) implemented the Hue, Saturation, Color, and Luminosity blend mode effects.

Why is that? Whenever fxc.exe would compile the .fx file (through the Shader Effects BuildTask and Templates), it would give me the following two errors:

  • error X5608: Compiled shader code uses too many arithmetic instruction slots (100). Max. allowed by target (ps_2_0) is 64.
  • error X5609: Compiled shader code uses too many instruction slots (102). Max. allowed by the target (ps_2_0) is 96.

Those errors mean that you’ve exceeded the limitations of Pixel Shader 2.0 … which is what WPF 3.5 SP1 targets for pixel shader effects.

So, what can you do about this? You could optimize the HLSL so that your effect code goes under the limits … but if you notice in the errors above (these particular errors are for the Saturation effect) … you will see that I am significantly above the number of allowed arithmetic instruction slots (100 versus 64). I would have to optimize significantly.

WPF 4.0 to the Rescue

Another option is to utilize WPF 4.0!

WPF 4.0 increases what you can do with effects because it now allows you to target Pixel Shader 3.0. This wikipedia article has a great chart on the differences between the different shader models. With PS 3.0, we shouldn’t hit any limits.

Realizing this, as soon as Visual Studio 2010 and .NET 4 Beta 2 came out (PS 3.0 is only available in Beta 2), I installed it and gave it a whirl. There was really only one gotcha in getting this to work. The Shader Effects BuildTask only compiles to PS 2.0 … and there is no option to toggle between PS 2.0 and PS 3.0.

This means that, for now, probably until release, you will have to manually run fxc.exe (targeting ps_3_0) and add the compiled shader output file (the .ps file) to the project as a Resource.

Caveats

There are some caveats to using PS 3.0 in WPF 4.0. Most notably, there is no software fallback if your hardware or situation (remote desktop, forced software rendering) don’t support it. This means that your effect code will simply not run and not appear.

Some good news is that Microsoft has extended the RenderCapability API so that you can determine what level of pixel shader support is currently available. They’ve updated the RenderCapability.IsPixelShaderVersionSupported method and have added two additional methods: RenderCapability.IsPixelShaderVersionSupportedInSoftware and RenderCapability.MaxPixelShaderInstructionSlots.

(The above information and more is available in David Teitlebaum’s PDC09 session titled Mastering WPF Graphics and Beyond. Jamie Rodriguez also has some great posts covering what’s new in WPF 4.0 (Beta 1, Beta 2).)

Another caveat that bears mentioning is that Silverlight (both 3.0 and 4.0) only support PS 2.0. So, if you are creating and using effects across both technologies, you will not be able to use PS 3.0. This also means that the Hue, Saturation, Color, and Luminosity blend modes (and the attached code) are WPF only blend modes. Sorry Silverlight! I love you, but that’s how the chips fall.

Hue, Saturation, Color, and Luminosity: Here They Are!

Alright … enough with the caveats! Let’s see the effects!

First, let me refer you back to Angie Bowen’s post where she covers what each blend mode does … including the Hue, Saturation, Color and Luminosity effects.

To show off what each effect does, I’m going to go ahead and use her reference images … first showing how they blend out of Photoshop … and then showing how they blend with my library … for comparison purposes. Why? Well, it seems as if my blend mode library does not always match what is coming out of Photoshop … sometimes it’s pretty darn close and at other times it’s more than just a little bit off.

I have been through and through the math (and HLSL) for these effects and I honestly can’t find anything wrong there. If I could speculate what is going on, I would say that I’m bumping up against some float versus double precision issues (where Photoshop is using doubles for greater precision) during the conversion from RGB to HSL and back. If you can figure out what I’ve done wrong (if anything) please let me know.

However, for the most part, they work great!

Hue Blend Mode

The result is the hue of the blend layer and the saturation and luminance of the base layer.

Photoshop

HuePhotoshop

My Blend Mode Library

Hue

Photoshop

Hue2Photoshop

My Blend Mode Library

Hue2

Saturation Blend Mode

The result is the saturation of the blend layer and the hue and luminance of the base layer.

Photoshop

SaturationPhotoshop

My Blend Mode Library

Saturation

Photoshop

Saturation2Photoshop

My Blend Mode Library

Saturation2

Color Blend Mode

The result is luminance of the base layer and the hue and the saturation of the blend layer.

Photoshop

ColorPhotoshop

My Blend Mode Library

Color

Photoshop

Color2Photoshop

My Blend Mode Library

Color2

Luminosity Blend Mode

The result is hue and the saturation of the base layer and the luminosity of the blend layer.

Photoshop

LuminosityPhotoshop

My Blend Mode Library

Luminosity

Photoshop

Luminosity2Photoshop

My Blend Mode Library

Luminosity2

The Binaries and the Source Code

Here is the source code for the library and here is the assembly.

Again, remember that this is a WPF-only release as Silverlight does not yet have support for Pixel Shader 3.0.

Also, all of these new blend modes are opacity aware … meaning that you can pull the opacity out of the upper layer to lessen the effect of the blend mode (see my last post on the matter).

Enjoy!

p.s.

At one point, I thought that the Shader Effects BuildTask and Templates was built into Visual Studio 2010. It appears I was mistaken about that. I have updated this post to indicate that.

Share

PDC 2009 Recap

I had the opportunity to attend my first PDC this year and it was great! The content was top-notch and it was extremely fun to meet a lot of the Microsoft guys (and non-Microsoft guys) that I’ve worked with over the years (albeit virtually).

Here is my recap of the event.

The basic story was around Windows 7, Windows Azure (cloud computing), Visual Studio 2010, .NET 4 (WPF 4), and Silverlight 4.

If you weren’t able to go, you can still take in all the content yourself at your leisure … as Microsoft has made it publicly available at http://microsoftpdc.com/Videos.

During the event, I also live tweeted most things I attended. Check out http://twitter.com/cplotts if you want a …  ‘as it happened’ feel for the event.

Sessions That I Attended

Session Code Session Title Presenters Notes
WKSP04 Getting the Most out of Silverlight 3 Ian Griffiths, Richard Griffin This workshop was tag team with Ian Griffiths covering basic Silverlight concepts and then how to go about hooking a Silverlight application up to some services. Richard took over and talked about using MVVM and MEF with Silverlight and ended the day showing how to use Blend to turn a screen shot into a living breathing application.
KEY01 Day 1 Keynote Ray Ozzie, Bob Muglia This keynote was all about Windows Azure and cloud computing. Of particular note was the announcement for Microsoft PinPoint … a new marketplace for online services … and the announcement for Microsoft Codename ‘Dallas’ which is Microsoft’s effort to treat data as a service (which they will make available through PinPoint).
CL09 How Microsoft Visual Studio 2010 Was Build with WPF 4 Paul Harrington This was a great session where Paul described how Microsoft rewrote Visual Studio using WPF. This was a major undertaking and they had to actually add functionality to the WPF API in order to make it happen. Also of note was the many keyboard interop issues that they tackled and how they did so. A great WPF session, especially for those doing interop.
CL30 Microsoft Expression Blend 3 for Developers: Tips, Tricks, and Best Practices DoRon Motter This was a quick lunch session where DoRon went through 9 quick tips on using Expression Blend.
CL14 Advanced Graphics Functionality Using DirectX Michael Oneppo This was the 2D DirectX session that I attended. Most of it went right over my head, but I would like to dive in and understand DirectX since WPF is built on top of it.
CL11 Advanced WPF Application Performance Tuning and Analysis Eric Harding, Bart De Smet In this session Eric and Bart go through some general performance truths and then show you how to use vmmap, .NET Memory Profiler, Perforator, Visual Profiler, Process Explorer, and xPerf to solve performance problems in the areas of memory, cold start, warm start, and runtime. This is a must watch session for software engineers using WPF.
KEY02 Day 2 Keynote Steven Sinofsky, Scott Guthrie, Kurt DelBene This was the big keynote. Steven Sinofsky started it by talking about Windows 7. Then Scott Guthrie talked about Silverlight 4 and the new functionality it brings to the table. Finally, Kurt DelBene wrapped it up with Office 2010 and Sharepoint 2010. A lot of stuff happened in between too: demos of hardware accelerated text rendering in IE 9, demos of SketchFlow, demos of cool Silverlight 4 goodness, and more. And of course I have to mention that they gave away a free laptop to all attendees! Awesome with a capital A!
CL31 Mastering WPF Graphics and Beyond David Teitlebaum This was the session I was looking forward to the most. David rocks and I am very interested in WPF and in graphics. David is the WPF Graphics Program Manager. In this session, he covered the new WPF 4 graphics features (new text rendering, layout rounding, animation easing, pixel shader 3.0 support, cached composition, and more). Another must watch WPF session, especially geared towards those working in graphics. They should’ve given David a two hour slot, it was like drinking from a fire hose.
CL15 Modern 3D Graphics Using Windows 7 and Direct3D 11 Hardware Michael Oneppo This was the 3D DirectX session that I attended. Good stuff, mostly over my head. It whetted my appetite though. There was a great slide on the D3D10 pipeline showing where each shader fits in.
CL20 Improving and Extending the Sandbox with Microsoft Silverlight 4 Joe Stegman This was a surprise session as this wasn’t announced until PDC itself and it was all about the work Microsoft has done to extend the Silverlight sandbox, and just in general to crack it open. Of particular note is the new elevated trust out of browser stuff … that allows you to do almost anything via COM Automation. This is a game changer and likely will prove beneficial to our own Silverlight efforts.
CL22 Attended CL22, Advanced Topics for Building Large Scale Applications with Microsoft Silverlight John Papa I have never heard John Papa speak, but he is excellent. And although the topic doesn’t suggest it … this talk was all about MVVM (the Model-View-ViewModel pattern). In the talk he talks about two main variations on the MVVM pattern and how to use Prism as a ‘gap filler’ where MVVM doesn’t provide any answers. This is a must watch session if you are doing WPF or Silverlight. The MVVM pattern is the industry de-facto standard and John explains it well and concisely. I myself will be going over this one again.
CL02 Microsoft Silverlight 3: Advanced Performance and Profiling Techniques Seema Ramchandani I was a little late to this session but the parts I caught were solid gold. Seema covered Silverlight graphics and performance and this talk fits right alongside Eric Harding’s and Bart De Smet’s WPF performance talk. Another must-see.
CL10 WPF 4 Plumbing and Internals Blake Stone This talk was probably the best of the conference. Ok, maybe that is unfair to the other great content, but Blake Stone did an amazing job describing some of the internals of WPF and many of the things that trip developers up. Here is a link to the slides and sample code. Needless to say, this WPF session is a must-watch.
FT24 Building Extensible Rich Internet Applications with the Managed Extensibility Framework Glenn Block This session is an introduction to MEF (Managed Extensibility Framework) which Microsoft is using internally in its own products. This is a great technology and Glenn always gives a good presentation.
CL35 Custom Behaviors for Advanced Microsoft Silverlight UI Effects Pete Blois Pete Blois is the guy who created Snoop. So, you have to love him. In this session, he shows the audience how to create custom Expression Blend behaviors, making it easy to drag, drop, and create compelling user experiences. If you have the Blend love, you’ll enjoy this session.
CL24 XAML Futures in Microsoft .NET Framework, Microsoft Silverlight, and Tools Rob Relyea, Michael Shim Rob Relyea and Michael Shim closed out the conference for me by talking about the new  and upcoming features in XAML 2009 (XAML 2006 is what is currently out there) and what has been going on in this space lately. Unfortunately, neither Silverlight 4 nor WPF 4 nor any of the tools take advantage of XAML 2009 yet.

Sessions That I Missed but Want to Watch

Session Code Session Title Presenters Category
CL13 Windows Touch Deep Dive Reed Townsend Touch/Multi-Touch Development
CL27 Multi-Touch on Microsoft Surface and Windows 7 for .NET Developers Anson Tsao, Robert Levy Touch/Multi-Touch Development
CL23 SketchFlow: Prototyping to the Rescue Christian Schormann SketchFlow
CL01 Microsoft Silverlight 4 Overview Karen Corby Silverlight
CL06 Networking and Web Services in Microsoft Silverlight Yavor Georgiev Silverlight
CL21 Building Amazing Business Applications with Microsoft Silverlight and Microsoft .NET RIA Services Brad Abrams Silverlight
CL03 DirectX 11 DirectCompute Chas Boyd DirectX
FT35 Microsoft Visual C# IDE Tips & Tricks DJ Park C#
FT11 Future Directions for C# and Visual Basic Luca Bolognese C#
FT31 Dynamic Binding in C# 4.0 Mads Torgersen C#
FT51 Future of Garbage Collection Patrick Dussud C#
FT07 The State of Parallel Computing Burton Smith Parallel Computing
FT21 PLINQ: LINQ, but Faster! Ed Essey, Igor Ostrovsky Parallel Computing
FT54 Power Tools for Debugging Sandeep Karanth, Kapil Vaswani Diagnostics, Debugging, Testing
FT16 Advanced Diagnostics, IntelliTrace, and Test Automation Habib Heydarian Diagnostics, Debugging, Testing
CL16 Optimizing for Performance with the Windows Performance Toolkit Michael Milirud Diagnostics, Debugging, Testing
VTL30 Managing Development to Inspire Innovation and Create Great Software Experiences Scott Stanfield, Bill Crow UX
VTL05 A New Approach to Exploring Information on the Web Gary Flake UX

What a great conference! Hope this recap helps you decide what to dive in on yourself and provides for some easy links to do so.

Enjoy!

Share

PDC 2009

PDC09Bling_Workshops_HandsDirty_240 PDC09Bling_General_WhatsNext_240

 

My employer has graciously sent me to PDC this year and I’m stoked!

In fact, I’m here right now … about to walk down to the convention center, get registered, and attend one of the pre-cons (I’m going to the Silverlight one with the two Griffs (Ian Griffiths and Richard Griffin)).

If you see me there … don’t hesitate to say hello.

Share

Blend Modes: Now Opacity Aware

After I wrote my trio of blog posts (1, 2, 3) about blend modes using pixel shader effects, I was toying around with it …

 

The Problem

… and noticed that it didn’t handle an opacity changes on the upper layer (B).

In fact, this was brought to my attention by a great blog post by Angie Bowen. In it she explains how the blend modes work and, she says:

Remember that to get better results you can also adjust the opacity of the upper layer.

Trying it out, revealed that some of the blend modes were okay, but most were not. Most of the blend modes would simply result in a black square if you pulled all the opacity out of the upper layer (B). This was obviously wrong, for if you pull all the opacity out of the upper layer (B), you should get the lower layer (A).

Argh!

 

The Solution

So, I dove back in on the blend mode math, trying to figure out what I needed to do to make these blend modes … opacity aware. That’s got a nice ring to it, doesn’t it!?

I started at the top of the list and got the NormalEffect working:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 inputColor;
    inputColor = tex2D(input, uv);

    float4 blendColor;
    blendColor = tex2D(blend, uv);

    inputColor.rgb = (1 - blendColor.a) * inputColor.rgb + blendColor.rgb;

    return inputColor;
}

Ok, the above math made sense. When the opacity of the upper layer (blendColor.a) was 1 (opaque), the result was just blendColor. Otherwise when the opacity of the upper layer was 0 (transparent), the result was inputColor.

So, I then started to tackle the darken blend modes (Darken, Multiply, …) and quickly ran into problems. It was at that point, that I ran into this post in the WPF Forum. My blend modes were rendering full black (not white), but it provided a crucial piece of knowledge.

Namely, WPF uses pre-multiplied alpha everywhere for performance reasons.

What does that mean? Well, it means that the RGB values for inputColor are already multiplied by the alpha value for inputColor and that the RGB values for blendColor are already multiplied by the alpha value for blendColor.

Ah! Do you see it? This explains why the blend modes were going to a black square when pulling the opacity out. Take the Multiply blend mode. In the above HLSL, it would be:

// R = Base * Blend
resultColor.rgb = inputColor.rgb * blendColor.rgb

So, if the alphas were pre-multiplied in and you were pulling opacity out of the blend (upper) layer … then blendColor.rgb would go to zero … which would cause resultColor to go to zero … which would cause the gradient square to go to black!

Thinking about this … brought about the general solution for making these blend modes opacity aware. I needed to simply:

  1. Un-pre-multiply the blend layer alpha value out.
  2. Apply the blend mode math.
  3. Then re-multiply the blend layer alpha value in again.
    Here is the HLSL for the opacity aware Multiply blend mode:
    float4 main(float2 uv : TEXCOORD) : COLOR
    {
        float4 inputColor;
        inputColor = tex2D(input, uv);
    
        float4 blendColor;
        blendColor = tex2D(blend, uv);
    
        float4 resultColor;
        resultColor.a = inputColor.a;
        // un-premultiply the blendColor alpha out from blendColor
        blendColor.rgb = clamp(blendColor.rgb / blendColor.a, 0, 1);
    
        // apply the blend mode math
        // R = Base * Blend
        resultColor.rgb = inputColor.rgb * blendColor.rgb;
    
        // re-multiply the blendColor alpha in to blendColor
        // weight inputColor according to blendColor.a
        resultColor.rgb =
            (1 - blendColor.a) * inputColor.rgb +
            resultColor.rgb * blendColor.a;
    
        return resultColor;
    }

    A few comments about the above code. Notice that I am clamp(ing) when I un-premultiply (i.e. divide) the alpha out. This assures that the RGB values will be between 0 and 1 (where 0 is black and 1 is white … HLSL operates in ScRGB color space). This is necessary since dividing by values close to 0 (blendColor.a) can yield large numbers or even positive infinity … which throws off the math.

Secondly, when I re-multiply the blend layer alpha value back in … I need to also properly weight the inputColor … just like I did in the NormalEffect above.

Finally, notice that I really don’t have worry about the opacity on the lower layer (A). I just pass its value off to the result by setting resultColor.a equal to inputColor.a.

Applying this general formula worked in all cases!

 

The Gradient Contour Test Harness

In order to verify that I was doing math correctly, and to see the effect of pulling the opacity out of the blend modes … I have built a new gradient test harness. I have called it the gradient contour test harness since it not only shows the A + B = R gradient squares but it also shows the R gradient square with contours … just like Paul Dunn’s post does when you mouse over the R squares.

It is extremely interesting (to me at least) watching the contours as you pull out the opacities.

For example, Here are three gradient contour squares for the Pin Light blend mode at opacity values of 1.0, 0.5, and 0.0:

Gradient Squares

Gradient Contour Squares

Opacity

PinLight1.00nc PinLight1.00

1.0

PinLight0.50nc PinLight0.50

0.5

PinLight0.00nc PinLight0.00

0.0

I have also included a button labeled ‘Swap’ which swaps the A and B layers … since not all blend mode effects are commutative.

The gradient contours were made possible via Dwayne Need’s library. Check out the code (the class Grayscale4Bitmap) and see this post for more info.

The Image Test Harness

I’ve also put opacity sliders in the image test harnesses. Let’s take a look at the Pin Light effect at opacity values of 1.0, 0.5, and 0.3.

Images

Opacity
PinLightImage1.0 1.0
PinLightImage0.75 0.50
image 0.3

As you can see … pulling out the opacity … lessens the effect that the upper layer/texture has on the lower layer … and proves the truth of what Angie Bowen was saying earlier about using the opacity of the upper layer to achieve better results.

 

The Binaries and the Source Code (aka The Goods)

So, as I’m fond of saying … without further adieu … here is source code for the Blend Mode library and here are the library binaries … now opacity aware!

I also have updated the Silverlight test harness (as always you will need the Silverlight 3.0 runtime).

p.s.

The gradient contour test harness is WPF only … you won’t find that on the Silverlight side. Maybe someday I’ll get my Silverlight test harnesses up to parity with what’s in the WPF test harnesses … but I can’t see when. Any one want to do it for me? Bueller? Bueller?

Share

An Ode to wfSpy

As I’ve mentioned before, I love user interface spying utilities and often find myself championing their use.

Today, I got a message from someone requesting the modifications we made to wfSpy. I’ve always wanted to publish them back to the community and tried to do so by contacting the original author. However, I never got any response.

wfSpy stands for Windows Forms Spy and so it is a spying utility for Windows Forms applications (and specifically for .NET 2.0 and forward). It is similar to Hawkeye, but is easier to use … and doesn’t have quite as much functionality.

We made several modifications to it but the notable two are as follows.

First off, a colleague (Don Kackman) of mine added the crosshairs ability. Take a look at the main window that comes up when you launch it.

image

If you click on the magnifying glass, drag it on top of a Windows Forms control, and release … the wfSpy properties window will then come up.

image

The wfSpy properties window shows all the properties on the control that you just selected … and not only can you view them … but you can also modify them (at runtime) as well!

The second notable change that we added was synchronizing the tree view (on the wfSpy’s main window) such that the control you selected … is the active ‘window’ selected.

This is extremely useful in the case where you have controls that are hiding other controls … and there is no way to select those hidden (or covered) controls with the crosshairs. In this case, you use the crosshairs to select the control you can select, and then you close the properties window and use the tree view to select the control you want. I would often turn the Visible property of a control on and off … to help me navigate through the tree of controls.

When utilizing the tree view synchronization feature … make sure you have a refreshed version of the current controls in the tree view … by clicking the ‘Refresh’ button on wfSpy’s main window. Otherwise, the synchronization logic might not be able to find the control (in the tree view) you selected.

So, without further adieu … here is the source code.

Hope it helps!

p.s.

Leave a comment if it does help you … I always enjoy hearing that my efforts have actually paid dividends. 🙂

p.s.s.

I have just (May 15th, 2012) pushed the sourced code to GitHub after receiving yet another request for the .NET 4.0 version.

It is at the following location: https://github.com/cplotts/wfSpy

Share

WPF & Silverlight Charting: A Logarithmic Axis

I love controls. Even more … I love graph controls. In fact, graph controls have been one of the main things I have worked on during my tenure at my current place of employment.

A small aside: I think it is what I was meant to do (i.e. work on graph controls). For, my name is … Cory Plotts. Plotts, you know, as in plots. Ok, never mind, that was lame. 😀

So, it was quite natural, and actually part of my job, to take a look at what Microsoft is offering in the WPF and Silverlight toolkits. I have to hand it to David Anson and the other fellows at Microsoft. They have taken a very nice approach.

First, almost everything is a System.Windows.Controls.Control that you can restyle and re-template to your heart’s content. So, that makes it very designable.

Second, I love the data binding model. They have decided to follow an ItemsControl like approach where you have an ItemsSource property that you just plunk your data into. Very nice. It literally takes you seconds to get something up and running.

Third, they are developing it … with Blend in mind. That is, they are trying to provide a positive Blend experience and have gone to pains to make it so. So, not only is it designable … but designers can actually use Blend to do their designing … instead of hacking through xaml in a code editor. Woot! Woot!

Now, this post is not going to be an introduction on how to start using the charting component. Many others have done that already. If that is what you are looking for … I would suggest that you go to this blog post by David Anson where he lists out lots and lots of links to other blog posts and articles. In fact, he is so nice … that he has even separated them out by difficulty level.

No, in this blog post, I am going to show you the fourth thing I love about this charting component: how extensible it is! And, I am going to do that by showing how I created a logarithmic axis by simply deriving from NumericAxis.

So, here’s the code (sorry for just dumping it all in one place … but it gives you a nice place to copy out the entire implementation at once):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace System.Windows.Controls.DataVisualization.Charting
{
    /// <summary>
    /// An axis that displays numeric values along a logarithmic range.
    /// </summary>
    [StyleTypedProperty(Property = "GridLineStyle", StyleTargetType = typeof(Line))]
    [StyleTypedProperty(Property = "MajorTickMarkStyle", StyleTargetType = typeof(Line))]
    [StyleTypedProperty(Property = "MinorTickMarkStyle", StyleTargetType = typeof(Line))]
    [StyleTypedProperty(Property = "AxisLabelStyle", StyleTargetType = typeof(NumericAxisLabel))]
    [StyleTypedProperty(Property = "TitleStyle", StyleTargetType = typeof(Title))]
    [TemplatePart(Name = AxisGridName, Type = typeof(Grid))]
    [TemplatePart(Name = AxisTitleName, Type = typeof(Title))]
    public class LogarithmicAxis : NumericAxis
    {
        /// <summary>
        /// Instantiates a new instance of the LogarithmicAxis
        /// </summary>
        public LogarithmicAxis()
        {
            ActualRange = new Range<IComparable>(1.0, 2.0);
        }

        /// <summary>
        /// Returns the plot area coordinate of a value.
        /// </summary>
        /// <param name="value">The value to plot.</param>
        /// <param name="range">The range of values.</param>
        /// <param name="length">The length of the axis.</param>
        /// <returns>The plot area coordinate of the value.</returns>
        protected override UnitValue? GetPlotAreaCoordinate(object value, Range<IComparable> range, double length)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (range.HasData)
            {
                double doubleValue = ValueHelper.ToDouble(value);
                Range<double> actualDoubleRange = range.ToDoubleRange();

                return
                    new UnitValue
                    (
                        length /
                        Math.Log10(actualDoubleRange.Maximum / actualDoubleRange.Minimum) *
                        Math.Log10(doubleValue / actualDoubleRange.Minimum),
                        Unit.Pixels
                    );
            }

            return new UnitValue?();
        }

        /// <summary>
        /// Returns the value range given a plot area coordinate.
        /// </summary>
        /// <param name="value">The plot area position.</param>
        /// <returns>The value at that plot area coordinate.</returns>
        protected override IComparable GetValueAtPosition(UnitValue value)
        {
            if (ActualRange.HasData && ActualLength != 0.0)
            {
                if (value.Unit == Unit.Pixels)
                {
                    double coordinate = value.Value;
                    Range<double> actualDoubleRange = ActualRange.ToDoubleRange();

                    double output =
                        Math.Pow
                        (
                            10,
                            coordinate *
                            Math.Log10(actualDoubleRange.Maximum / actualDoubleRange.Minimum) /
                            ActualLength
                        )
                        *
                        actualDoubleRange.Minimum;

                    return output;
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            return null;
        }

        /// <summary>
        /// Returns a sequence of values to create major tick marks for.
        /// </summary>
        /// <param name="availableSize">The available size.</param>
        /// <returns>A sequence of values to create major tick marks for.
        /// </returns>
        protected override IEnumerable<IComparable> GetMajorTickMarkValues(Size availableSize)
        {
            return GetMajorValues(availableSize).Cast<IComparable>();
        }

        /// <summary>
        /// Returns a sequence of values to plot on the axis.
        /// </summary>
        /// <param name="availableSize">The available size.</param>
        /// <returns>A sequence of values to plot on the axis.</returns>
        protected override IEnumerable<IComparable> GetLabelValues(Size availableSize)
        {
            return GetMajorValues(availableSize).Cast<IComparable>();
        }

        /// <summary>
        /// Returns a sequence of major axis values.
        /// </summary>
        /// <param name="availableSize">The available size.</param>
        /// <returns>A sequence of major axis values.
        /// </returns>
        private IEnumerable<double> GetMajorValues(Size availableSize)
        {
            if (!ActualRange.HasData || ValueHelper.Compare(ActualRange.Minimum, ActualRange.Maximum) == 0 || GetLength(availableSize) == 0.0)
            {
                yield break;
            }

            yield return 125;
            yield return 250;
            yield return 500;
            yield return 1000;
            yield return 2000;
            yield return 4000;
            yield return 8000;
        }
    }
}

To explain the above code a little bit, I would first direct your attention to two methods. The first is called GetPlotAreaCoordinate. This method is the method responsible for converting from world coordinates into device coordinates. That is, it converts all the data point values in your Series into pixel coordinates … so that your data point is placed where you expect it should be.

The second method is called GetValueAtPosition. This method does the exact opposite as GetPlotAreaCoordinate. It converts from device coordinates into world coordinates. In other words, it takes the mouse position (for example) and it tells you where your mouse is at on the respective axis.

So, the above two methods contain the math behind the axis … and if you look closely, you’ll see the Math.Log10 function getting called. Yep. That’s right. This is a logarithmic axis.

After those two methods, you will see GetMajorTickValues and GetLabelValues. They both delegate to a third method called GetMajorValues. GetMajorTickValues returns the values at which we want major tick marks and GetLabelValues returns the values at which we want grid line labels. Pretty straightforward.

Now, a word about my implementation of GetMajorValues. In it, I have chosen to hardcode very specific values for this axis’ grid lines (i.e. 125, 250, 500, 1000, 2000, 4000, 8000). I did that because I was lazy. For inside of LinearAxis, there is an Interval property which you can use to generate the grid lines in a dynamic fashion … and I didn’t feel like figuring out how to make the Interval property work for the logarithmic axis. (If anyone out there does take the time to do so … please share!)

So, more than likely, you will be wanting to replace those specific values with some of your own … or will be wanting to generate the major values in a much more dynamic way.

Ok, now let me show you how you would use this axis. Check out this xaml (this is just a snippet … I am leaving out all the styling xaml and more):

<charting:Chart
    x:Name="chart"
    Width="480"
    Height="480"
    Margin="10"
    Title="Response"
    BorderBrush="{x:Null}"
    Style="{StaticResource chartStyle}"
>
    <charting:Chart.Axes>
        <charting:LogarithmicAxis
            Orientation="X"
            ShowGridLines="True"
            Title="Frequency (Hz)"
            Minimum="100"
            Maximum="10000"
        />
        <charting:LinearAxis
            Orientation="Y"
            ShowGridLines="True"
            Title="Response (dB SPL)"
            Minimum="20"
            Maximum="120"
            Interval="10"
        />
    </charting:Chart.Axes>
    <charting:LineSeries
        ItemsSource="{StaticResource responseCurve}"
        IndependentValueBinding="{Binding Frequency}"
        DependentValueBinding="{Binding Response}"
        DataPointStyle="{StaticResource lineDataPointStyle}"
        AnimationSequence="Simultaneous"
        TransitionDuration="0:0:0"
        IsSelectionEnabled="True"
    />
</charting:Chart>

In the above, you can see my new and proud LogarithmicAxis with a Minimum value of 100 and a Maximum value of 10000. Here is a snapshot of the chart that the above xaml creates:

image

Woot! Doesn’t it look sweet!

Now, go out and create some logarithmic charts!

p.s.

I have had to make these changes in a local edit of the toolkits. However, as David Anson points out in this post … they are unsealing everything! So, in a little while … you will no longer need to do this. You will be free to simply derive a new axis at your leisure. In my mind, that is another point for extensibility!

p.s.s.

Here is the source code for this article … note that it contains David Anson’s development release version 1 … and it contains his DataVisualizationDemos applications. Finally, and most importantly for this article, it contains the sample code for the above … under the title Visibility (I was working on some DataPoint visibility functionality at the time I drafted up that test harness).

p.s.s.s.

David Anson and the fellows at Microsoft have finally released the version of the Silverlight Toolkit that unseals everything. Check out this blog post for more info. When David publishes another development release, I’ll update the source code for this article so that the above is not a local edit.

p.s.s.s.s.

I have finally gotten around to getting the source code together where the above logarithmic axis is just an extension of toolkit … versus the local edit as before. So, here is that source code. It is actually from David Anson’s development release 3 (although I have stripped out the WPF 4 and Silverlight 4 projects). I won’t remove the above source code … as some people might want to see both ways of doing it.

One additional comment. In David’s development release 2, there was an internal NumericAxis constructor. So, even though he unsealed everything, that internal constructor was inhibiting me from inheriting a new numeric axis type via an extension. That meant I had to wait till development release 3 in order to provide this code. (I also had to find some time too. :D)

p.s.s.s.s.s.

I have finally decided to crack out the WPF 4.0 and Silverlight 4.0 version of my logarithmic axis above as several people have expressed confusion and frustration trying to get it to work.

The source code can be downloaded here.

This source code is based on David Anson’s development release 4 version (i.e. here for the core bits and here for the test harnesses).

Please note that you should open up DataVisualizationDemos4.sln from the downloaded code as that solution contains all 4 projects: the 2 core projects and the 2 test harness projects. The 2 test harness projects have project references to the assemblies built in the 2 core projects.

Also note that you should unload either the Silverlight 4 test harness … or the WPF 4 test harness, when running, setting the other one as your startup project … as I have had problems with the built executables/bits for the test harnesses stomping on top of one another.

Finally, once you get it running, there is a ‘Logarithmic Axis’ test harness. Good luck!

Share