Welcome to MSDN Blogs Sign in | Join | Help

Silverlight Toolkit March 2009 Release

This week we released an updated Silverlight Toolkit - the Silverlight Toolkit March 2009 release.   This release has some new components, but we spent a lot of time working to make sure that the Toolkit can be updated in an agile way, but still fits in nicely with other platform and tools releases.

Goals for the March 2009 Release

1. Align the Toolkit with the SDK

The main thing that we wanted to establish was a smooth flow of components from the Toolkit into the platform, in this case the SDK.  Most Toolkit components are things that people will want to have in their default tooling experience, and one of our goals is to minimize the number of things that developers must download to get productive with the platform.  So the first order of business was to setup the Toolkit to be primarily an incubation vehicle for SDK components.  So most components start in the Toolkit, and end up eventually in the SDK that comes with Visual Studio or Expression Blend.

This also meant pulling the existing SDK controls into the Toolkit package.  With the March 2009 release, you'll find the source code for all of the Silverlight 3 versions of the SDK controls - DataGrid, Calendar, TabControl, etc.  As with the rest of the Toolkit, this code is licensed under MS-PL so you're free to modify it or use it in your application.

2. Do the work to support Silverlight 2 and Silverlight 3

With Silverlight 3 coming into the picture, we needed to structure the Toolkit project to be able to handle both versions.   Our philosophy is to do as much work in the Silverlight 2 Toolkit as possible, then just do things in Silverlight 3 that have a dependency on the new runtime.  We'll continue to support Silverlight 2 up through the release of Silverlight 3, then we'll focus on Silverlight 3 exclusively as customers upgrade.  On the Release page you'll see a Silverlight 3 Beta and Silverlight 2 installer.

3. Fully support the Blend and Visual Studio development environments

I've always been a big believer in delivering great design-time experiences.  We've done a lot of work with the tools teams to make sure that our components work well with the designers, including having items in the Toolbox and having the right properties show up in the tool. This turned out to be more work than we had anticipated and we're hopeful that any customers that are writing components can use what we've done as a good example of how to make all of this stuff work. We'll keep pushing on making this a great experience over time.

4. Address critical customer feedback

The biggest piece of feedback we've gotten is to have our Samples available in VB.NET as well as C#, so we did the work to make that happen. 

image

In addition, we've fixed the highest-voted bugs in components across the Toolkit including Charting,  AutoCompleteBox, and TreeView.  Thanks to everyone that took the time to file issues or vote, that data is very helpful to us.  One catch here is that some of our components (like TreeView) need to maintain API compat with WPF, so that limits the type of changes that we can make.

We also now have an MSI-based installer package that installs the Toolkit for you and gets the Toolkit control items into the Visual Studio Toolbox or Blend Asset Panel automatically.  This helps with the discovery of components and makes them easier to add to your projects.  It also sets up a nice Start Menu entry as well:

image

5. Add new controls

We've also added some new controls - Accordion, DomainUpDown, and TimePicker, all of which are in the Preview band for this release.  Check them out!

Toolkit Namespace and Assembly Changes

If you're upgrading from a prior version of the Toolkit, you'll notice that the namespace names for most components have changed from Microsoft.* to System.*.  So for this upgrade, you'll need to go through the process of updating your code, so sorry for that up front.

This was something we spent a *lot* of time talking through.  The original reason for making the Toolkit components be in Microsoft was so that we could add components to the SDK or the Core and not have them conflict with Toolkit versions.  We wanted there to be an opt-in change when developers moved from a Toolkit control to the platform version - we'd delay the need for the user to make a change until the very end.  But the user would need to update source code.  The more we thought about this, and talked to customers, the more it seemed like this wasn't the right thing to do since it means more-and-more code that you'll need to fix up if you wait longer.  Instead, for the components we expected to make it into the platform, it was better to put them into their final namespace and then physically move them into the platform assembly when they were fully mature.  This meant having a new Toolkit build with each platform release that has those types removed.  But that's something we do anyway, and doing it this way means that customers only need to update their references and maybe their XAML xml namespace, and that's it.  Code should continue to run.  We decided that was a better model.

In conjunction with that, we needed to make sure that installing or using the Toolkit was something that didn't disturb the supported platform release.  So that meant Toolkit assemblies had to be able to sit side-by-side with SDK assemblies.  To accomplish that, we appended the word "Toolkit" to the Toolkit assemblies and that makes an easy mapping for where things are in the Toolkit to where they will end up in the SDK.

Here is an example:

Today, System.Windows.Controls.Accordion is in System.Windows.Controls.Layout.Toolkit.dll.  Someday in the future, Accordion will reach the Mature Quality Band and then a platform release will happen and it will be moved into the SDK.  When the next version of Silverlight ships, we will ship a corresponding Toolkit and SDK.  The Accordion component will move into System.Windows.Controls.Layout.DLL (note no "Toolkit" in there), which is part of the SDK itselfDevelopers using this component will need to add a reference to that SDK assembly and (optionally) remove the reference to System.Windows.Controls.Layout.Toolkit.dll if it's not needed anymore.  The developer would also need to update their XML namespace definition to point to the SDK version of the DLL so that the XAML parser knows where to find it.  That should be it, and the project will now be using the SDK version of the component with no code changes.

What this unfortunately means is that we've got quite a few assemblies coming out of the Toolkit.  We've tried to intelligently bucket the Toolkit controls into a few different assemblies so you don't have to pay to have a bunch of components in your XAP you're not using.  We'll do the same thing for the SDK.  But given the above, you get 2 assemblies for each bucket.  Unfortunately, that's the simplest solution even if it's a little verbose.

Rebuilding SDK Components

As I mentioned above, the full source for the SDK components is now present in the Toolkit project.  The Toolkit only includes source for these components, not the components themselves.  Many parts of the system (for example Blend) are tested and built against the released version of the SDK components.  We don't want the Toolkit updating these by default, but we do want to allow developers to make fixes to these components and deploy them with their applications if needed.  In the Toolkit you'll find a Toolkit solution and an SDK solution so there is a nice separation there.  If you do make a change to one of these components, you can just update the reference in your project to your rebuilt version and run against that.

image

Other Improvements

The Toolkit also includes two great new themes: Bubble Cream and Twilight Blue.

We've added AreaSeries in the Charts

image

 

 

Looking forward to hearing your feedback!

Posted by sburke | 6 Comments
Filed under:

WPF and Silverlight Toolkit Compatibility

General Compat Thoughts

The majority of the controls in the Silverlight Toolkit November 2008 (PDC) release are Silverlight versions of controls already present in WPF.

These "WPF Parity" controls include:

  • DockPanel
  • WrapPanel
  • ViewBox
  • Label
  • Expander
  • TreeView
  • HeaderedContentControl
  • HeaderedItemsControl

We focused heavily on API compatibility for these controls, only making changes (I'm actually not sure if there were any) for things that aren't currently possible on the Silverlight 2 runtime.  And some things, like supporting Visual State Manager, required internal changes that made the process more complicated than just copying the existing WPF code. 

We did leverage the WPF control specs and use the WPF controls behavior as our guidelines, and we were pretty hard-core about making sure the Silverlight Toolkit control's API was a strict subset of the corresponding WPF control's API.  One of the primary compatibility goals was also to enable sharing of design assets, via VSM between WPF and Silverlight with minimal changes, and this enables that as well.

Even so, the controls aren't "strictly" compatible for two main reasons:

  1. CLR Namespace: All of the Silverlight Toolkit controls are in the Microsoft.* namespace instead of the System.* namespace.  We made this change for a variety of reasons, some of which I mentioned in a prior post.  Basically we want our "out-of-band" controls to be in "Microsoft.*" and the platform ones (e.g. in the core runtime) to be "System.*".  The main benefit of this is that when/if we decide to move controls into the runtime they will NEVER collide with the existing ones and therefore won't break any applications.  This then is an opt-in model for developers for when they want to swap over to the runtime controls
  2. XML Namespace: Silverlight doesn't currently support the same XML namespace semantics that WPF does.  In WPF you can use the XmlnsDefinitionAttribute to "collapse" multiple CLR namespaces into a single XML namespace.  Silverlight's parser doesn't currently support this, hence the need to have a separate XML namespace for each CLR Namespace + Assembly pairing, and you need to have a prefix for that in your XAML.

The upshot of all of this is that, to move your code from Silverlight to WPF, for the "parity" controls listed above, you'll need to do two things:

  1. Change your using/Imports* clause to be System.Windows.Controls from Microsoft.Windows.Controls.
  2. Remove the xmlns declaration and the prefixes from the XAML. So  <controls:DockPanel /> becomes <DockPanel/>, for example.

The constraints outlined above made it difficult to make compat "Just Work" at this point in time.  Doing so would have required a set of complex tooling changes and too many "moving parts" that could result in broken applications or versioning issues.  As such, our main goal was to make this compatibility experience simple, consistent, understandable, and something the compiler can help you with.  All of which tend to be my preferences in most cases.  It's much easier for us to implement and deliver, while being easy for developers to manage.  At some point we may add some help to automate this if developers do have trouble with it.

How Compat Affects The Silverlight Toolkit

Which brings me to the point of all of this.

Looking at the CodePlex IssueTracker, there are quite a few issues reported that are more feature requests than bugs.  Unfortunately, many of these are things that we can't do without affecting the "subset" compat that I mentioned below.

For example, there are several of these relating to the the TreeView:

TreeView: Drag & Drop, Inline Node Editing

TreeView: Ability to Cancel TreeViewItem Selection

TreeView: Showing Connecting Lines in TreeView

We are having some conversations about how to handle this.  The optimal solution would be for us to be able to have a derived TreeView class that does all this stuff, that we can then port back over to WPF so the same "extended" functionality works there.  Another option would be to write a separate "TreeViewEx" that does this, but that brings with it the potential for a lot of confusion and duplication.  And in both cases, we're investigating how many of these modifications can coexist peacefully.  We're still investigating.

In any case, this is an area where we're happy to take feedback on or any other ideas about how best to handle this.

 


* when controls move from the Toolkit such that a control exists in both places for some amount of time you may need to do an explicit "using DockPanel = System.Windows.Controls.DockPanel;" disambiguation.

Posted by sburke | 5 Comments

A Veritable Cornucopia of Silverlight Toolkit Resources

The Silverlight Toolkit is off to a great start and lots of people have been spending time writing content about how to use it.

I'm a big believer in delivering a good end-to-end experience with the software my team produces, and the Silverlight Toolkit is a great example of that.  More than just some controls, we've got documentation, tests, and now a great variety of blogs.

WARNING: Incoming link storm - there is a LOT of stuff out there

Silverlight Toolkit Team Blogs

The team has been really been cranking out the blogs.  Take a look at these...

In every case above, the person writing the article was involved in the development of the component they're referencing.  So you're getting it right from the source!

Other Resources

Okay, my fingers are cramping from too much CTRL+K, COPY, PASTE action so I'll stop there. I hope I didn't forget or miss too many (if so I apologize).  I'm in awe of all of this stuff and how awesome these posts are.  If one of the posts doesn't answer your question, the team has been very active on the forum!

Happy Silverlighting!

Posted by sburke | 2 Comments
Filed under:

Having problems opening the Silverlight Toolkit Help file?

Today at lunch, Jeff mentioned to me that the default security policy on Windows Vista was causing some users difficulty opening the CHM help file.

Jeff has all the details on his blog.

You'll get a message that says "Navigation was canceled".

If that's the case for you, just right click the file, choose "Properties" and then hit the "Unblock" button at the bottom of the dialog.

Posted by sburke | 3 Comments
Filed under:

PDC "Silverlight Controls Roadmap" talk and materials

Just arrived back home from a great few days down at PDC in LA.  What a fun show to be at - even for people inside the company it's a great opportunity to learn about some of thee great projects going on.   I'm really excited about Live Mesh and am looking forward to learning more about Azure and the services it offers.

My talk is now available online here, and I've attached my talk materials below.

The ChartBuilder demo is available on David's blog along with a nice write up.

The response to the Silverlight Toolkit has been VERY positive and you'll be seeing me write more about our plans and what we have going on with that.

Posted by sburke | 2 Comments
Attachment(s): PDC08.zip

Silverlight Toolkit Now Available For Download

On the heels of Scott Guthtrie's PDC keynote this morning, I'm very pleased to announce the launch of the Silverlight Toolkit on CodePlex!

image

The Silverlight Toolkit is a collection of components dedicated to making you - the Silverlight Developer - as productive as possible writing Silverlight.  The full Silverlight Toolkit is available under the Microsoft Public License, an OSI-Approved license that allows full reuse of the code.

If you've read my last few posts, you know we're doing a slightly different release model.  Based on what we learned with the AJAX Control Toolkit, Scott asked me to build a team focused on writing controls for Silverlight and WPF that could do so in a rapid, agile way.  The Silverlight Toolkit is the first delivery from that team.

Download it here.

Release Model

We are focused on a rapid, feedback-centric release model.  Our goal is to update the Silverlight Toolkit releases roughly every 6-8 weeks - gated mostly on when we have "critical mass" of features or functionality.  Each release may contain new components, bug fixes, or both.

We've delivered the Silverlight Toolkit as a set of assemblies, instead of just one.  We wanted to make sure that Silverlight Applications can pick the components they need and not pay to download all the ones they don't.  So we looked at all the components we're releasing today, and some that we're considering in the future and came up with some high level "buckets" that are easy to remember and give us room to grow.  Each of these buckets represent an Assembly in the Silverlight Toolkit.

  • Common - the Silverlight Toolkit base classes and components that we think a large percentage of applications will be using.  This contains AutoCompleteBox and the layout controls.  Default prefix is "controls".
  • Input - components that take user input.  For this release, only NumericUpDown and it's base classes are in here.  Default prefix is "input".
  • DataVisualization - this contains the charting components.  Default prefix "charting".
  • Layout, Media - these are DLLs (buckets) that don't have any components for this release, but expect to see them in the future.

Quality Bands

There are two different ways that you can do software releases.  The traditional way is to hold an entire release until all components reach, roughly, the same quality level.  This works fine but forces all of your users to wait for everything.  It's a bit of an agility buzz kill.   Another method, is to have a single, rolling, release vehicle which has components different quality levels.  This works fine, provided you can clearly designate which components are at which level so users can make informed decisions about what they are using.

Enter Quality Bands, which are high-level buckets that describe a given components API stability and overall finish level.  This concept ties in with the Issue Tracker on the CodePlex site.  Users file and vote on bugs, and we continue to improve the component in response to that feedback.  It's the nature and the volume of that feedback that helps us determine when to move a component to the next band.  As you move up the Quality Band scale, you'll get components that are mode dependable for a wide variety of projects.

What are the Quality Bands?  We've designated four of them:

Experimental - components that are added to garner scenario or usefulness feedback.  These may not have a future in the Silverlight Toolkit.

Preview - these are components that we have made a commitment too and we think will work for ~80% of the major scenarios.  Many components are relatively simple and if you just need the basic functionality, these may work for you.  We always do our best to minimize "breaking changes" in APIs or behavior, but components at this band may see some level of this as we perfect the API.  Think of this as Alpha quality, give-or-take.

Stable - these components have moved out of Preview and should handle 90+% of scenarios.  We'll hold any breaking changes to a higher bar but if something is really wrong, we'll change it.   Something like Beta quality.

Mature - these components are at full "RTM" quality and fit-and-finish.  These components will not have breaking changes (except in rare critical situations like security issues) and are usable in a broad range of scenarios.  The API stability is key here - by using these components, our goal is that upgrading from one Silverlight Toolkit release to another should be a no-brainer.

The Silverlight Toolkit contains a CHM help file, and if you navigate to any of the component's documentation, you'll see the Quality Band clearly marked at the top.  On the CodePlex site, we've also added information about this.

Controls in the Mature band are eligible to be released with the Visual Studio Tools for Silverlight package, or in the Silverlight Runtime itself if appropriate.

As you'll see below, all of the components in the Silverlight Toolkit are in the Preview or Stable bands, as this is a Preview release.  And, because we haven't taken any feedback from the community, nothing can be in Stable or Mature, by definition.  We're hopeful we can quickly move many of these components up through the bands!

New Silverlight Controls and Components

We have a great set of components available.  You may have noticed from the image above that Charting has made it into the Silverlight Toolkit!  The team has been working literally 24-hours a day to get charting into this release.  We've been very focused on getting the right charting architecture and API model in place, at the cost of some more flashy scenarios.  We're now confident that we are in a place where we have made the right decisions and we'll be able to quickly add chart types and animations. What sets our charts apart is that they fully take advantage of the powerful styling and templating model that's present in Silverlight.

image

Not only do we support templating (your truly made the template above, believe it or not!), but we do support dynamic update.  If the chart above is attached to an ObservableCollection-based data source, you'll see the bars animate as your data changes.  It's very cool (UPDATE: example animation here at Tim's blog).

AutoCompleteBox is a great component as well.  It allows full templating as well as super-easy "out of the box" scenarios where you just attach it to a collection of items.  It's very flexible.  Check out this AutoCompleteBox with a DataGrid as the drop down:

image

This sample searches all columns with the word "New".

Of course there is more, and here's the full list of components and their Quality Bands.

Theming Containers

image

Another major goal of the Silverlight Toolkit is to help developers build good looking applications on this great Silverlight platform.  So in this release you'll see six new themes that you can use in your application.  We will also be making these themes available on WPF.

Silverlight lacks a WPF feature known as "implicit styling", which allows the theme for a type of component - say, Button - to be defined centrally.  One of the powerful attributes of the Silverlight Toolkit is that it allows us to deliver "stopgap" functionality to help developers outside of the main Silverlight ship-cycle.  In this release, we have a component called Implicit Style Manager (ISM) that allows to do this in a way that is similar to WPF. 

We're leveraging ISM to deliver these themes in a very simple way.  Each theme is available in raw XAML, or in a DLL.  In this DLL, is the theme and a "theme container".  For using it, just add a reference to the theme DLL to your project, then wrap your UI with that container.  Done!

Before: XAML: After:
image

<shiny:ShinyBlueTheme>
<StackPanel Margin="10" >
  <Button Content="Button"/>
   

  <CheckBox Content="CheckBox"/>
  <RadioButton Content="One"/>
  <RadioButton Content="Two"/>
  <basics:Calendar/>
</StackPanel>
</shiny:ShinyBlueTheme>

image

There's lots more.  With the Silverlight Toolkit project, we've got a great sample site that shows all of the components and how to use them, and we've got more components and themes on the way!  This site is also hosted on Silverlight.net here.

image 

Note at the top you can see the running sample, the XAML, and the C# code it took to build it.  Play around with it - there's lots to do there.

Information and Support

There are several ways to get support on the Silverlight Toolkit:

I hope this has given you an idea of what we've been up to and where we are headed.  Let us know what you think!

Posted by sburke | 29 Comments
Filed under: ,

Silverlight 2 Released - Silverlight Toolkit on the Way

As you know, today we released Silverlight 2.  Scott mentioned the Silverlight Toolkit in his post as well - which is exactly what my team is working on.  We're driving hard to get the first preview release of the Silverlight Toolkit at PDC later this month.

Just to reiterate a few points that Scott called out.  We'll be doing the release under an OSI license (MS-PL) and we will again be including unit tests and a testing harness.   The harness is something that you're welcome to use in your projects, I talked about it a few weeks ago.   We're including the tests themselves so that developers will be able to have plenty of examples about how to write tests, but also it allows some level of coverage for any modifications users choose to make to the controls themselves.

Keep watching this blog for updates on the Silverlight Toolkit and how we're progressing.  In the meantime, here's a screen shot of just a few of the controls in action, with different themes applied. 

 

ControlsPPCT (4)


(No, we're not doing an Outlook control...that's just example content.)

Lots more to come.

Posted by sburke | 22 Comments
Filed under: ,

MEF 'n IoC

If you understood the title of this post, then you'll understand the question that's been in my head for a few weeks.  Recently, Microsoft released a preview of the Microsoft Extensibility Framework (MEF) up on CodePlex.  As I do with most things when first explained to me, I attempted to bucket MEF in terms of something I already understood.  So, the first thing I thought of was "oh, it's an IoC thing".  The person explaining to me said that it wasn't, but it wasn't clear to me at the time what it actually was.

Since then it's been on my list to sit down and write something using MEF to get this figured out.

Fortunately, at a meeting yesterday, Brad did a quick MEF demo (which I now see is exactly what he put on his blog, making me fell less special).  This nicely knocked a "to-do" off of my list and now I get it.  So, in case you're wondering about this same thing, here goes.

MEF is not an IoC container.  You can use it kind of like one, but that's not what it's really meant for.  And if you're doing Dependency Injection, you should stick with StuctureMap or Ninject or whatever you're using already.  MEF is basically using some IoC-like principles to enable application composition and dependency management.  So in some way it's kind of like IoC for your application.  It's focused on discovering components and letting your application compose itself on the fly.  It's designed for larger applications like Visual Studio.  Now that I understand it, and, yeah, it's pretty darn cool.

In my opinion, IoC is more about a consistent loose-coupling pattern across your app, and in many ways the factories act like smart service providers, with the containers adding a variety of ways to configure how query resolutions are done at a particular point in time (e.g. they allow you to register bindings in config or in code, statically or dynamically, etc.)

Hopefully that helps anyone else out there.  If you pull down the MEF code expecting it to be an IoC container, you'll be pretty confused.

-----

Reference: Ayende's post was helpful in explaining this as well.

Posted by sburke | 2 Comments

Unit testing with Silverlight

image One of the things I was most excited about when we shipped the Silverlight 2 Beta 1 controls was the included unit testing harness, written by Jeff Wilcox.  I think it's a good thing when we can share some of our internal tooling.  It's good for customers, because they can leverage the work that we've been doing, and it's good for people here because it gives them a chance to "ship" something and get some visibility in the industry.  And this is definitely the case with the Silverlight Unit Test Framework, which Jeff has just updated for RC0.

This is the exact package that we're using internally to run our automated unit tests and we've been adding features to it as our team grows.  Oftentimes, development teams here at Microsoft use a different testing harness from what the testing teams use (please don't ask...) and I'm keen to avoid that setup, and the Silverlight Unit Test Framework provides the functionality for both.  And that we're allowing customers to leverage it opens up some other possibilities that I'll get into later.  Note that the Silverlight Unit Test Framework is an unsupported toolset, not an official Microsoft product.

Some of you may be asking why we wrote our own unit testing harness instead of using something like nUnit or MbUnit.  The main reason is because the existing offerings were all written against the full .NET Framework.  Even though Silverlight is .NET code, it really is a different platform.  And it has some special needs due to the constraints on the type of reflection you can use (public only) and how you're able to instantiate and discover tests.  So we decided we needed a harness that was written fully in Silverlight and hosted the tests directly in the harness itself.  This has worked out well.

So if you're starting to get rolling with Silverlight, and you want to do some unit testing, definitely give the Silverlight Unit Test Framework a look.

More details here.

Posted by sburke | 6 Comments
Filed under: ,

Updated ExpandoHeaderControl sample for RC0

Here is the updated control sample for RC0.

 Just a few changes from Beta 2 - RCO:

  • generic.xaml needs to now be in a folder called "themes" (case sensitive) rather than in the root of your project. 
  • In VSM transition declarations "Duration" has been renamed to "GeneratedDuration"

So porting was easy.  If you want to play with this, definitely load it up in Blend and check out the great new VSM support as well.  It make re-templating MUCH easier and I had some fun creating weird collapse effects (not included).

 

Posted by sburke | 8 Comments
Filed under: ,

Attachment(s): HeaderControl.zip

Control Freak.

Hmmm...no blogging lately...what has Shawn been up to? 

Yes, guilty.  But here's what's been going on over the past few months.  Shortly after MIX07, ScottGu brought up an idea of building a larger team focused on building controls.  We kicked this idea around for while as we talked about details, timelines, and goals.  In April, most of these details were worked out and we hashed out a charter and some early areas of focus and deliverables.

The problem we saw was that we had a bit of a fragmented controls story.  My team (the Agility Team that brought you the AJAX Control Toolkit, etc.) had been writing some controls.  The core Silverlight team was writing some controls.  The UIFX Team (which brought you ASP.NET and Windows Forms) was writing some controls.  The WPF team was writing controls.  You get the idea.  So Scott asked me to build a team that would unify these various efforts, in strategy if not in implementation.  And the Controls Team was born on April 28th, 2008.  After reporting to Scott for a little over two years, my team and I popped down to report to Ian Ellison Taylor, GM of the WPF and Silverlight teams and veteran of all things "UI-Platform" at Microsoft for over 15 years.

Sooooo...what exactly will you be doing?

Good question.  My team owns the charter for both Silverlight and WPF control development.  That means doing most of the engineering, planning, and development of controls.  But it also means figuring out other ways to get controls into the toolbox for developers to use.  For example, if another team is developing a control that might be generally useful, we'll try to figure out a way to get it into our deliverable.

The team is being built mostly from scratch.  So while we are ramping up and getting people hired in, we're focusing primarily on Silverlight controls.  Meanwhile, I have been working with the WPF folks helping them get some controls delivered to - the first of which is the DataGrid now available via the WPFToolkit.  I am definitely committed to improving the controls story on WPF as well.

One of the reasons Scott asked me to build this team is to continue the work we've been doing around pioneering transparency and agility in our software development process here at Microsoft.  The open model of the AJAX Control Toolkit really broke a lot of new ground, and we continued some of that with the Silverlight 2 Beta 1 Controls we did when we shipped not only buildable source, but our unit testing harness, and tests too!

Who is on this team you speak of?

All Stars.  Some of them you may already be familiar with. 

David Anson, Ted Glaza, Jeff Wilcox, Ning Zhang, Mehdi Slaoui Andaloussi, Beatriz Stollnitz (Costa), Justin-Josef Angel, Jafar Husain, Shawn Oster, Keith Smith, and just this week, Ruurd Boeke.

That's some horsepower right there, I tell you what.  I really couldn't ask for better people, and we've got more to hire!

What about the AJAX Control Toolkit?

The AJAX Control Toolkit is in good hands.  We've transferred ownership over to the ASP.NET team, and Bertrand is leading the effort.  They've already started making good progress and I'm very excited about what they're planning for the future.

Okay, so when will you be shipping something?

Right.  Good question.  We are currently working on a set of controls for a preview release at PDC 2008 in late October.  This will be a preview release, but we feel good about the quality bar that we think we can hit nonetheless.  Because we're using a slight different development model, our controls will be released earlier, improve evolutionarily over time, so there isn't a clear "RTM" date for them.  But in any case, we're doing a preview at PDC. 

Here's a list of the Silverlight controls we are currently working on that we think will be ready.  We are working on some other components as well, but I'm leaving them off the list until we have higher-confidence about them being ready:

  • DockPanel
  • WrapPanel
  • ViewBox
  • Label
  • HeaderedContentControl
  • Expander
  • TreeView
  • NumericUpDown
  • AutoComplete
  • Accordion

All of these controls will use the new Visual State Manager templating model and be fully customizable in XAML by hand or through Expression Blend.  They will also ship with full, buildable source, unit tests, and an updated unit testing harness nicely wrapped up with a tasty OSI-Approved MS-PL license.

Wait as second...what's this 'slightly different' model?

Another good question.  Part of it, as noted above, is that we're going to be aggressive about shipping early and shipping source.  We'll be leveraging many of the learnings from the AJAX Control Toolkit as well as the SL2 B1 Controls efforts.

Basically, it is based on an iterative, customer-centric delivery model that focuses on driving out the most critical customer issues over time.

Sometime between now and PDC, we will be launching a CodePlex project for our Silverlight components (as a sibling of the WPF project mentioned above).

Here's how it works:

  1. When a new component reaches "80%" quality - that is it meets the scenario needs of ~80% of customers - it will be added to the project.
  2. The project will have frequent releases when there is a critical mass of customer value (say, bug fixes or new components) that justifies a release.  Think every 6-8 weeks or so.
  3. Each release will include the components, documentation, sample code, and unit tests.  You, as the user are free to modify, copy, or redistribute the components however you see fit.
  4. Customers will file bugs/issues with the components via the CodePlex Issue Tracker.  Issue Tracker has a great voting facility built in.  We will prioritize our bug fixing and/or enhancement work based heavily on this voting.  Highly voted-for issues get fixed first, with some discretion based on cost/complexity.  For example, if the #2, #3, and #4 issues are easy fixes, they may get done ahead of a complex and difficult #1 issue, for a particular release.
  5. A given component, over time, will reach a very high quality level.  Throughout this process, two things will happen.  First, the "bar" for fixing a bug will go up.  That means, as the component stabilizes, we will be more-and-more careful about which fixes we accept.  Second, and as a corollary to the first, as the component stabilizes, we will be enforcing a stricter-and-stricter bar with respect to breaking changes.  This will happen pretty quickly.  A component that is "new" may have some amount of API changes as we react to feedback.  But after a release or two, we will lock down the API and behavior so that these components are very stable and easy for users to upgrade as new releases come out.  This is critical.  We're working on a way of marking (think metadata attributes and docs) each component to call out which  "stage" it's in, but the goal is to get them API stable relatively quickly.  Because we do frequent releases, upgrading to each new release has to be a "no-brainer".
  6. For all new components, goto (1)

So over time you have a rolling release that is getting more and more featureful.  I don't know if 'featureful' is a word but if it's not, I'm coining it as a term right here!  Anyway, you get the idea.  If you want just the "baked" stuff, you can stick to the mature components.  If you have a need for another newer component, you can use those too.   It's up to you.

Over time, you will see some (maybe many) of these components work their way into either the Silverlight Core, or the Silverlight SDK as fully-supported components like you are used to.  That's the beauty of this model - it offers quick delivery at the front end for more cutting-edge customers, and the traditional "I got it with VS" model for customers that prefer that.

When we start focusing on WPF components in the future, we'll be following a very similar model.  Just replace "Silverlight Core/SDK" with ".NET Framework" and you'll get the idea.

In contrast to the AJAX Control Toolkit, we will *not* be accepting any customer contributions of fixes into the code base.

So that's what I've been up to.  It's very exciting, stay tuned for more details!

Posted by sburke | 48 Comments
Filed under: ,

Updated Silverlight Control Tutorial for Silverlight 2 Beta 2

I've finally gotten the Silverlight Control tutorial sample updated for Silverlight 2 Beta 2.

There have been some non-trivial changes to how controls are written between Beta 1 and Beta 2.  My goals were to do more than a straight port.  I wanted to take advantage of some of these changes as an example of how to use the new functionality, and I wanted to address some feedback I've gotten from the original post.  Some of the ways I chose to do things in the original post were overly complicated, and I took this opportunity to streamline things a bit.  The result is the same functionality with a lot less code.

Default template

The major change centers around the Visual State Manager.  When my team and I first started working with Silverlight, we found the existing templating model to be difficult and confusing.  The model of defining all of your animations as key-framed timelines was work intensive and difficult to get right.  In addition, the model of having parts and states defined in the same way led to what we called "state explosion".  This occurred with controls like the CheckBox when you get into permutations of states - "Checked Focused MouseOver", "Checked Unfocused MouseOver"..."Unchecked Unfocused MouseOver"..."Checked Disabled"....you get the idea.  Each time you added another axis, you added another state to define and it quickly got out of control.  I think CheckBox had 18 states at one point.  Not good.

We brought this up with the Blend team and they came up with a great solution to the problem: Visual State Manager.  Not only did this simplify things by allowing the system to compute may of the transitions, but it also allowed Blend to implement a MUCH nicer tooling experience (Tim has a great overview here).   Doing this conversion was the first time I'd used this in action and the difference is dramatic.  I'm so glad we were able to do this.   We got together with the Blend and Silverlight teams and workout out a way to get it into the platform.  It's a huge win.

The other changes are simplifications and updates due to changes in the Silverlight platform (there weren't many of these).

Basically, in my original sample, I wasn't taking advantage of binding properly.  So I had some properties and parts I didn't need.  Moreover, I committed some "no-nos" like including code in my CLR property wrapper for accessing a Dependency Property.  Fixing these issues up really smoothed things along.

And, finally, in the app.xaml, I included to very basic templates to show what a simple template would look like.  One collapses horizontally, the other vertically:

Horizontal Collapse vertical collapse

To give you an idea how much things are simplified using VSM. here are some before and after code samples:

Beta1:

        protected override void OnApplyTemplate()

 

        {

 

            base.OnApplyTemplate();

            // Fish out all of the template children and wire them up.            //

 

            _rootElement = GetTemplateChild(ExpandoHeaderControl.RootElement) as FrameworkElement;

            if (_rootElement != null)

 

            {

 

                bool opened = IsOpened;

                _buttonElement = GetTemplateChild(ExpandoHeaderControl.ButtonElement) as ToggleButton;

 

                if (_buttonElement != null)                {

 

                    // setup the buttons initial state.

 

                    //

 

                    _buttonElement.IsChecked = opened;

 

                    _buttonElement.Click += new RoutedEventHandler(ToggleButtonElement_Click);

 

                }

 

                _openAnimation = _rootElement.Resources[ExpandoHeaderControl.OpenAnimation] as Storyboard;

 

                _closeAnimation = _rootElement.Resources[ExpandoHeaderControl.CloseAnimation] as Storyboard;

 

            }

 

            ChangeVisualState();

 

            _templateLoaded = true;

 

        }

 

        private void ChangeVisualState()        {

 

            // manage the animations base on the current state.

 

            //                       

 

            Storyboard toState = IsOpened ? _openAnimation : _closeAnimation;

 

            Storyboard fromState = !IsOpened ? _openAnimation : _closeAnimation;

 

            if (toState != null)            {

                if (!_templateLoaded)                {

 

                    toState.SkipToFill();

 

                }

 

                else                {

 

                    toState.Begin();

 

                }

 

            }

            if (fromState != null)            {

 

                fromState.Stop();

 

            }

 

        }

Beta 2:

        public override void OnApplyTemplate()        {          

            base.OnApplyTemplate();

 

            // fetch the button and hook up to it's click event.

 

            //

 

            _buttonElement = GetTemplateChild(ExpandoHeaderControl.ButtonElement) as ToggleButton;

 

            if (_buttonElement != null)            {

 

                _buttonElement.Click += new RoutedEventHandler(ToggleButtonElement_Click);

 

            }           

 

            // set up our initial state

 

            //

 

            ChangeVisualState(false);           

 

        }

 

        private void ChangeVisualState(bool useTransitions)        {

 

            // Tell VSM to manage the animations based on the current state.

 

            //                                   

 

            VisualStateManager.GoToState(this, IsOpened ? NormalState : ClosedState, useTransitions);

 

        }

Much simpler!  Note the call to VSM in the ChangeVisualState method.

The other changes to call out.  To get generic.xaml to work, you need to specify a DefaultStyleKey in your constructor:

        public ExpandoHeaderControl()        {       

            DefaultStyleKey = typeof(ExpandoHeaderControl);

 

        }

Also note OnApplyTemplate is now public.

Other than that the process is basically the same as documented in the prior tutorial.  Inside of the generic.xaml file, you'll see how I templated the ToggleButton.  The animation on ToggleButton took me a long time on Beta 1, and I never got it quite right.  With the Blend June Preview that supports VSM, this was a snap.

Posted by sburke | 5 Comments
Filed under:

Attachment(s): HeaderB2.zip

Building a Storefront using ASP.NET MVC

If you're interested in what's going on with the new ASP.NET MVC project, Rob Conery has just launched a new series of webcasts that document the process of him building out an MVC Storefront.  He's been iterating on this idea for a few weeks and it's coming together very nicely - I think you'll find it a nice change of pace from standard webcast fare.

Rob's ASP.NET MVC Storefront Series

Posted by sburke | 0 Comments

Tutorial: Writing a Templated Silverlight 2 Control

[UPDATE: For a Beta 2 version of this control, click here

We're going to create this control:

image

It's called the ExpandoHeaderControl, and it does two basic things.  First, it has an area for a header, and a collapsible content area, with a ToggleButton to manage when the content is visible or not (e.g. collapsed).

For this tutorial, I'm trying to simplify concepts as much as possible. For more sophisticated, industrial-strength concepts, check out the full control source available for the Source Code for Silverlight 2 Beta 1 Controls.

I'm continually amazed by how much power Silveright 2 provides.  This control will require about 100 lines of code to write.  Really!  Let's get started.

Step 1: Defining your control's template parts. 

What are the parts of your control that the logic has to interact with?  These should be the the defined "parts" of your control.  There are two types of objects that your control cares about.  First, it's the elements that are going to drive the UI or layout.  And, second, are the transition Storyboard animations that will cause your control's UI to move from one state to the next.  Let's focus on the UI parts right now.

We want to make sure that we give designers the most flexibility possible.  So our code should be as general as possible.  If you look at the code in the Silverlight 2 Beta 1 Controls package, you'll see great examples of this.  The code running the control is very agnostic about what the UI is actually doing.

So for our control, we'll define a few parts:

  1. The RootElement, which is the container for all of the UI.  This is important because it's also where we'll stick the resources that have our Transitions.
  2. The HeaderElement, which is the element that contains the header content.
  3. The ContentElement, which is the element that will parent the main content in the collapsible area.
  4. The ButtonElement, which is the ToggleButton that will control the collapsed state.

Usually, when we start writing our control, the first step is to add these attributes to our control class:

   [TemplatePart(Name=ExpandoHeaderControl.RootElement, Type=typeof(FrameworkElement))]
   [TemplatePart(Name=ExpandoHeaderControl.HeaderElement, Type=typeof(ContentControl))]
   [TemplatePart(Name=ExpandoHeaderControl.ContentElement, Type=typeof(ContentControl))]
   [TemplatePart(Name=ExpandoHeaderControl.ButtonElement, Type=typeof(ToggleButton))]    
   public class ExpandoHeaderControl : ContentControl
   {        
       private const string RootElement = "RootElement";
       private const string HeaderElement = "HeaderElement";
       private const string ContentElement = "ContentElement";
       private const string ButtonElement = "ButtonElement";  

Note that we do two small, but important, things here.  First, we use static strings for the element names.  This is good practice because we'll use them again later.  Second, we specify what type of element the Template Part needs to be.  This should be the most general type that you need for a given element.  If you use specific types here (for example Grid instead of FrameworkElement for the root), it will be much more difficult to template your control.  In the case of the ButtonElement, we chose ToggleButton rather than Button so we can ensure that it has a specific state.  If we used just Button (or ButtonBase), we'd need to track this ourselves. 

Step 2: Define your control's transition animations

What are the animations that your control will need to transition from one state to the next?  Defining transitions is just the same as defining the parts - use the TemplatePart attribute.  The main difference here is that the type will always be Storyboard.

Let's add in the animation declarations:

[TemplatePart(Name=ExpandoHeaderControl.RootElement, Type=typeof(FrameworkElement))]
    [TemplatePart(Name=ExpandoHeaderControl.HeaderElement, Type=typeof(ContentControl))]
    [TemplatePart(Name=ExpandoHeaderControl.ContentElement, Type=typeof(ContentControl))]
    [TemplatePart(Name=ExpandoHeaderControl.ButtonElement, Type=typeof(ToggleButton))]    
    [TemplatePart(Name = ExpandoHeaderControl.OpenAnimation, Type = typeof(Storyboard))]
    [TemplatePart(Name = ExpandoHeaderControl.CloseAnimation, Type = typeof(Storyboard))]
    public class ExpandoHeaderControl : ContentControl
    {        
        private const string RootElement = "RootElement";
        private const string HeaderElement = "HeaderElement";
        private const string ContentElement = "ContentElement";
        private const string ButtonElement = "ButtonElement";        
        private const string OpenAnimation = "OpenAnimation";
        private const string CloseAnimation = "CloseAnimation";

Step 3:  Write your OnApplyTemplate logic

After a control is loaded, its UI is populated from it's template.  To do this, the override of OnApplyTemplate is called by the framework.   For the most part, this code always looks about the same. 

For each of your parts, you're likely to want to have a member variable to access the element later, if you'll need to manipulate it:

        private FrameworkElement _rootElement;
        private ToggleButton _buttonElement;
        private Storyboard _openAnimation, _closeAnimation;
        
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // Fish out all of the template children and wire them up.
            //
            _rootElement = GetTemplateChild(ExpandoHeaderControl.RootElement) as FrameworkElement;

            if (_rootElement != null)
            {
                     
                _buttonElement = GetTemplateChild(ExpandoHeaderControl.ButtonElement) as ToggleButton;
                _openAnimation = _rootElement.Resources[ExpandoHeaderControl.OpenAnimation] as Storyboard;
                _closeAnimation = _rootElement.Resources[ExpandoHeaderControl.CloseAnimation] as Storyboard;
            }
        }

One thing to note is that we access parts and transitions differently.  Note how we access the transitions out of the root element's Resources collection. 

Step 4: Create any properties you'll want to bind to in your template

Silverlight and WPF have a feature called Template Binding.  Template Binding allows you to "pass through" settings from a control to the UI defined in the Template.  For example, imagine your control has a TextBlock in it.  You'd like to be able to set the font properties of that TextBlock in a way that doesn't force the user to understand how the template is put together.  Template Binding allows you to reference properties on the object being templated and set those values into the template, similar to data binding.

Our control has two content areas:  the header, and the content itself.   Since our control derives from ContentControl, it already has a property called "Content" that we can use for the main content area.  But we want another one called HeaderContent to specify that, so we'll create one.  For a property to be bindable, it has to be defined as a DependancyProperty.  Visual Studio 2008 has a built in snippet for defining these.  It's meant for WPF, but it's close enough.  Just type "propdp".

image

When you do this, fill in the various fields.  In this case, the property's type should be object, and it's called HeaderContent:

       // Content property for the header
       //
       public static readonly DependencyProperty HeaderContentProperty =
           DependencyProperty.Register("HeaderContent", typeof(object), typeof(ExpandoHeaderControl), null);

       public object HeaderContent
       {
           get { return (object)GetValue(HeaderContentProperty); }
           set { SetValue(HeaderContentProperty, value); }
       }

The snippet also creates the CLR property with accessors as well!

Step 5: Create a simple Template for Testing

Okay, now it's time to throw some UI in there.  We'll create a very simple template that does everything we need.

<Grid x:Name="RootElement">
        <Grid.Resources>
            <Storyboard x:Key="OpenAnimation">
                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="(UIElement.Opacity)">
                    <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.0"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
            
            <Storyboard x:Key="CloseAnimation">
                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="(UIElement.Opacity)">
                    <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
            
        </Grid.Resources>
    <Grid.RowDefinitions>                                
        <RowDefinition Height="50"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="30" />
    </Grid.ColumnDefinitions>
        <ContentControl  HorizontalAlignment="Left" Background="Red" Content="{TemplateBinding HeaderContent}"/>
        <ToggleButton Grid.Column="1" HorizontalAlignment="Right" x:Name="ButtonElement" Content="X"/>
    
    <ContentControl Grid.ColumnSpan="2" Grid.Row="1"  Grid.Column="0" x:Name="ContentElement" 
                    Content="{TemplateBinding Content}" Background="Blue"/>
    
    

</Grid>

Okay, there's our template.  When instantiated, it looks like this:

image

Told ya it was simple.  Let's take a look at what parts we have in the template and how they match up with the control.

In the template, we define the animations at the top as resources off of the RootElement.

Notice we reference them by Key, not by Name.

For this control, we've defined a 2 row, 2 column Grid for our layout.  In the top row, we have the HeaderElement and the ButtonElement.  In the second row, we have the ContentElement, with a RowSpan of 2 so it fills up the bottom.  The red area and the words "header" and "Content Area" come from the control's usage, not the control itself or the template (see below).  In the Template above, you'll see two instances of "TemplateBinding" like "{TemplateBinding HeaderContent}".  When the control is templated, it will substitute the value of the controls "HeaderContent" property in that position. 

In our main XAML page, we've declared this control like this:

<my:ExpandoHeaderControl Width="200" x:Name="Header" Style="{StaticResource SimpleTemplate}" HeaderContent="header">
                        
       <my:ExpandoHeaderControl.Content>
          <Grid>
             <Rectangle Fill="Red" Stretch="Fill"/>
             <TextBlock Text="Content Area" HorizontalAlignment="Center" VerticalAlignment="Center"/>
         </Grid>
       </my:ExpandoHeaderControl.Content>

</my:ExpandoHeaderControl>

You may be wondering where to put that template.

In most cases, the Template will either be inline with the control's declaration (as it's Template property value, example in Step 8 below) in the XAML. This is good for one-off templates but doesn't let you share a template across controls. The more common way is as a resource defined in App.XAML (as we've done here). then it's hooked us as a StaticResource into the controls style property, as you see above.

Step 6: Managing State Changes

Now we've got the UI working, but the button doesn't know what to do when we push it.   Let's go back to our code and fix that.

The way this is usually done is to create properties to represent the state of your control.  In our case, the main piece of state is whether-or-not the control is collapsed.  So we'll add a property "IsOpened" to manage that.

// Property that determines if the expando is opened.
//
public static readonly DependencyProperty IsOpenedProperty =
    DependencyProperty.Register("IsOpened", typeof(bool), typeof(ExpandoHeaderControl), new PropertyChangedCallback(NotifyIsOpenedChanged));

private static void NotifyIsOpenedChanged(DependencyObject dpObj, DependencyPropertyChangedEventArgs change)
{
    bool isOpened = (bool)change.NewValue;

    ((ExpandoHeaderControl)dpObj).IsOpened = isOpened;
}

public bool IsOpened
{
    get
    {
        if (_buttonElement != null)
        {
            return _buttonElement.IsChecked ?? false;
        }
        else
        {
            return (bool)GetValue(IsOpenedProperty);
        }
    }
    set
    {
        if (_buttonElement != null)
        {
            _buttonElement.IsChecked = value;
        }
        else
        {
            SetValue(IsOpenedProperty, value);
        }
        ChangeVisualState();
    }
}

This looks a bit complicated.  We want to be able to bind to this property, so we've declared it as a DependancyProperty.   And we want to make sure it mirrors the actual state of the button, so if we have one of those, we'll just use its checked state.   But if we don't have one from the template, we'll just fall back to our own value.

One other note - we're hooking the changed value here.  If someone changes this value, we want to know about it so that we can update our state.  When the DP changes, our static handler will be called.  From that, we figure out which control fired the change, and update the state as appropriate.

Now that we've added the property, we can add some code in OnApplyTemplate to hook up to the Button's Click event:

bool opened = IsOpened;

_buttonElement = GetTemplateChild(ExpandoHeaderControl.ButtonElement) as ToggleButton;

if (_buttonElement != null)
{
    // setup the buttons initial state.
    //
    _buttonElement.IsChecked = opened;
    _buttonElement.Click += new RoutedEventHandler(ToggleButtonElement_Click);
    
}

Finally, we want a unified place to manage the state animations.  For that we've created a method called ChangeVisualState which plays the right animations for each state change.

This code may look funny, but to make sure we handle the case of an interrupted transition, we should start the "to" state StoryBoard before stopping the "From" one.

void ToggleButtonElement_Click(object sender, RoutedEventArgs e)
{
    // just update our state.
    //
    ChangeVisualState();
}
private void ChangeVisualState()
{
    // manage the animations base on the current state.
    //                        
    Storyboard toState = IsOpened ? _openAnimation : _closeAnimation;
    Storyboard fromState = !IsOpened ? _openAnimation : _closeAnimation;

    if (toState != null)
    {
        
        if (!_templateLoaded)
        {
            toState.SkipToFill();                    
        }
        else
        {
            toState.Begin();
        }
    }

    if (fromState != null)
    {
        fromState.Stop();
    }
}

We now have a working control!

Step 7: Specifying your default template

You'll notice that all of the SL 2 Beta1 controls have a nice default look and feel to them.  How is this accomplished?  Well, it takes a small amount of trickery.

The way you do this is by defining a XAML file called "generic.xaml" in your project and specifying it as a resource:

image

The Silveright Runtime will look for this resource and hook up templates for each specified type.  Your generic.xaml should look like this:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:HeaderControl;assembly=HeaderControl">

<Style TargetType="local:ExpandoHeaderControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ExpandoHeaderControl">
                    <!-- template xml -->
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

Step 8: Making it look nice!

I've been slowly going through Blend Kindergarten over the last few weeks.  I finally managed to get the hang of making nice glassy looking UI and was able to create a template to match.  If you'd like to learn this stuff, I highly recommend the tutorials over at the Liquid Boy blog.  They're simple and quickly taught me enough to be dangerous to myself and others.

I spent quite a bit of time mocking up the UI you see at the top of this post, and I think it looks pretty good.  Notice that I also templated the ToggleButton (as a nested template inside of the ExpandoHeaderControl Template in generic.xaml.

<ToggleButton Margin="4" Grid.Column="1" x:Name="ButtonElement" IsChecked="true">
    <ToggleButton.Template>
        <ControlTemplate TargetType="ToggleButton">
            <!-- glassy round Toggle Button Template XAML -->

        </ControlTemplate>
    </ToggleButton.Template>                                
</ToggleButton>

After I got the hang of this, it became a lot of fun.  The glassy look on the toggle button, and the funny little arrow didn't take too long to put together really.  For someone who doesn't have an ounce of design sense, I'm quite proud of myself.

Finally, here's how the control is declared on the page:

<my:ExpandoHeaderControl x:Name="sample" HeaderContent="Choose Color">
            
        <my:ExpandoHeaderControl.Content>
             <ListBox x:Name="lb" Height="100">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid Margin="2" Width="180">
                            <Rectangle Stretch="Fill" Fill="{Binding}"/>
                            <ContentPresenter Content="{Binding}"/>
                        </Grid>
                    </DataTemplate>                                
                </ListBox.ItemTemplate>
             </ListBox>                       
        </my:ExpandoHeaderControl.Content>

    </my:ExpandoHeaderControl>

Note the "{Binding}" syntax in the data template. Usually you specify a property in there like {Binding Name}, but in this case we're just using the item value itself, as in this case we're binding to an array of strings.

Again, here's the final, working product (if you're on IE/FF on Windows at least, not sure about Safari on Mac - shoehorning this into the blog has issues :))

 

Attached is the full project.  Enjoy!

Posted by sburke | 17 Comments
Filed under:

Attachment(s): HeaderControl.zip

Silverlight 2 Beta 1 Controls Available, including Source and Unit Tests

Get Silverlight 2 Beta 1

If you were watching the Keynote from MIX08, you know that Silverlight 2 Beta 1 is now available for download.

The package includes three components:

1) The Silverlight 2 Beta 1 Runtime - installs the basic Silverlight runtime components

2) The Silverlight 2 SDK - includes - installs tools for building Silverlight applications including the controls

3) Microsoft Silverlight Tools Beta 1 for Visual Studio 2008 - installs a project system for Silverlight that works on Visual Studio 2008, including Silverlight XAML Intellisense, Expression Blend interop, and a design-time view of the Silverlight app that you're building.

Get the Source for the Controls

A few months back, we pulled together a team to build out this list of controls.  As part of this effort, we wanted to make sure we delivered something that would really help customers with using the Beta 1 bits. 

So we decided to do to things:

1) Provide source code for the components so users can use it as a sample, or to make changes to the components themselves.

2) Within that project, also ship the Unit Tests that our developers used when writing the components.

You can also download the Silverlight 2 Beta 1 Controls project package now.  The code in this package exactly matches the controls included with the Silverlight 2 Beta 1 SDK download (for example, TextBox, Image, etc. are implemented directly in the runtime).

Simply download the package and unzip it somewhere on your machine using the self-extracting zip.  Once you've done that, launch the project using the "MixControls.sln" solution in VS 2008.

When you launch the solution, you'll see six projects:

Controls - contains basic controls like Button, Checkbox, etc.

Controls.Extended - contains controls like Calendar, Slider, etc.

Controls.Data - contains the DataGrid control

Controls.Test - Unit tests for the Controls project

Controls.Extended.Test - Unit tests for the Controls.Extended project

Controls.Data.Test - Unit tests for the Controls.Data project

Controls Project Test Projects, Controls.Data, Controls.Extended

As expected, all the source code for the controls is in the project.

image

Testing Silverlight Control Code

You can then run the unit tests for any of the projects by launching it's corresponding "Test" project.  Our test harness runs inside of the browser and runs the unit tests.  There are a lot of them -- almost 1500 for the Controls assembly alone! -- and we've gotten very good code coverage.  In the case of the Controls.Test project, for example, we know we're getting over 80% code coverage from our unit tests.  This facility has allowed us to have very few regressions in our control development work, as well as quickly spot any possible issues in the underlying Silverlight runtime when we pick up daily builds. 

Silverlight Control Unit Tests

As you'd expect, the unit tests are basic but provide some functionality that you need for testing in an animated environment like Silverlight.  For example, if the template for a component defines animations, you need to wait for those to run and for the component to be added to the visual tree before checking the state.  You can't do this synchronously, and you can't access the UI thread from another thread.  So we came up with a unique easy to use system for this that handles all that for you, but still lets you write tests that are in one method and are easy to maintain.

Here's an example:

 

image

CreateAsyncTest takes the component, adds it to the Silveright surface, waits for it's Loaded event to fire, then runs the delegate function you've provided (in this case we're using the C# 3.0 Lambda syntax).  It's very clean and simple and allows very rapid writing and execution of tests.

In the controls themselves, you'll also see lots of things to help you write your own control.  In each controls project, you'll find a file called generic.xaml.  This is where you will find the default templates for all of our controls.  You can either customize this in place, or (preferably) use it as a starting point for creating your own templates.

To use these controls in your Silverlight project instead of the default, just add the DLL to your references as you would with any other .NET project and you're set.

More Resources

We're working on getting more sample apps up to help you do usage and templating of controls, but the online docs really are great, including videos and traditional MSDN content.  For example, check out this topic on templating a Button.  Keep an eye on Silverlight.net for more example apps.

I've found the code in these controls invaluable when building Silverlight applications.  I think you will too!

Posted by sburke | 30 Comments
Filed under: ,
More Posts Next page »
 
Page view tracker