Friday, December 26, 2008

A Solution to DataGrid with Tooltips Shortcomings

DataGrid with a Custom RowDetailsTemplate
Silverlight RTM has a DataGrid control. To learn more about basic usage, please refer to http://blogs.msdn.com/scmorris/archive/2008/03/21/using-the-silverlight-datagrid.aspx

Beyond the basics, DataGrid has a few shortcomings. Let's say we have a static DataGrid declaration that looks like this:







































Where the ItemsSource of the DataGrid is defined by a List collection:


public class GridData
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public bool Available { get; set; }
}


DataContext of Grid not associated with ToolTip's DataContext by default
The first annoyance is ToolTip does not inherit the DataContext (entry in the List) associated with the Row that contains it. Compiling the above code will result in the Record # binding picking up the correct Binding while the custom ToolTip.Content will not.



The Solution is to add a handler for a Loaded Event to the Grid that begins our DataTemplate definition:
 
<grid loaded="Grid_DataContext_Fixer">
<tooltipservice.tooltip>
<tooltip></tooltip>
</tooltipservice.tooltip>
</grid>

Inside the handler, we use the ToolTipService to manually set Grid's DataContext to the DataContext of the Tooltip like so:

private void Grid_DataContext_Fixer(object sender, RoutedEventArgs e)
{
ToolTip t = ToolTipService.GetToolTip(sender as Grid) as ToolTip;
t.DataContext = (sender as Grid).DataContext;
}


The ToolTip will now properly understand the binding.



Sorting DataGrid will break ToolTip associations
When user sorts the DataGrid ToolTips are not re-ordered along with the view.



Why this happens is not clear. ToolTipService does bind to the right Object reference yet the DataContext remains tied to the ordering of items in the original List.

A Solution. This time we add a MouseEnter event handler to the same Grid.


<grid loaded="Grid_DataContext_Fixer" mouseenter="Grid_DataContext_Fixer">
<tooltipservice.tooltip>
<tooltip>...</tooltip>
</tooltipservice.tooltip>
</grid>


In fact, the MouseEnter event will do exactly the same thing as before. Namely, the Grid's context will be reassigned to the Tooltip. As shown above, we handle both events with the same handler.

We now get expected behavior.



If you have a better solution, please do provide feedback in the Comments.

Thursday, December 18, 2008

Twitter is Google Search in Reverse

Remember the search interfaces of yester-years? Pulldowns, check boxes, and operands defined the experience until Google stripped it all away. The exposed input box felt naked next to its companions. Yet the babe had brawn. Over the years the ubiquitous search box came to dominate content retrieval because of its simplicity, expressiveness, and relative clairvoyance. You typed some text in, Google rewarded you with a best guess of information you must have been looking for.

Our utterly selfish "give me" relationship with Google quickly earned Google medals in advertising. We were still putting enough "in" to Google's Engine for it to quasi-cleverly match up your key words with the highest-bidding, and content-relevant advertiser.

Spin up to today and we have a similar input box delivering 140 characters of further indulgence. "Give me" seemed to evolve social consciousness into an "I am". Our passive-aggressive social cloud is bloated with micro-summaries of people's whereabouts, whatchados, grandiose plans colored by nuance and mediocrity. And what with it? Nothing. Or rather nothing much.

Those still riding the web2.0-enabled Collaboration and Productivity opportunities are escaping email for what they hope to be a Twitter-gendered repose from Info Glut. But this is naivete. Every medium for communication will only alleviate over-saturated predecessors until usage turns into abuse-age. A much savvier colleague of mine had an insight that, paraphrased, in the consumer world, Twitter creates communication where it does not already exist. In the workplace, however, we are trying to better direct our information traffic, to reduce abuse, to improve relevancy, and tune interruption.

Twitter is a cloud of unstructured data. This data is time sensitive. A classical use case is "What am I doing now?". Stretched a bit we can evolve to "I am planning something right now that I will do shortly" and "I have just done something stranger and friends alike should know about".

As is, this glorified presence system is prime for integration with our Instant Messaging Clients' Status Notes or Away Message. But this is not very exciting. As the significance of any single Twitter fades with passing seconds into oblivion, what are we, the Information Workers, gaining from such an exchange? A Status Feed is great, but really, just the tip of the ice berg.

Sometimes actual Knowledge is Twittered. For example, "I just read a great article on Silverlight about Animations at http://..." or "Firebug just crashed on me after visiting a site with Google Ads again!".

The first sample is clearly relevant to people interested in Silverlight. The second is clearly a bug report and a stability alarm. Perhaps unfiltered noise in the consumer cloud but in the Enterprise access to these streams of consciousness is the very essence of the next generation's competitive edge.

And so Twitter must become the reversed flow of Google-like search.

In the Enterpise, search blankets our repositories and knowledge bases, constructing a uniform way for retrieval. Twitters (micro-content, really) must be deconstructed and filed back in. To be able to distinguish Status from Knowledge and to create on-demand availability of this type of information mashed up with related information is the cosmic pixie dust of the future.

Speaking of the future, Twitter recently acquired Values of n for I Want Sandy, a personal digital secretary. If Twitters about "right now" generate Knowledge then Twitters about the future must generate Activities. Activities produce Knowledge: more Twitters, CRM information, documents, blog posts, etc. When all this information is accounted for it truly seems that the personal Digital Assistant need not be so personal after all.

To move beyond this "give me" towards a notion of Coordinated Intelligence, we will need to embrace Semantics, Context, Community-friendly Knowledge Management strategies, and that bit of nakedness. I'll race you there.

Monday, September 29, 2008

Silverlight RC0 Custom Controls: App.xaml vs Generic.xaml

Motivation
Silverlight 2 RC0 is now available to developers and early adopters. Summary of release and Breaking Changes are reproduced in my previous post available here.

Best Practices around developing Custom Controls is still a shaping story. Many tutorials currently available on the web prefer the use of App.xaml or the UserControl itself for custom styling and templates. In fact, Styles and Templates are still a bit confusing from a design and usage perspective.

The existence of yet another option, the use of generic.xaml further confuses approach to styling. For those of you who have been scratching their heads as much as I have been, I hope that the basics I'll outline in this and future posts will help the Silverlight community refine the "right" way approach Custom Control creation, Styling, and Templating.

Goals
• Propose strategy for using Generic.xaml and App.xaml
• Project structure should enable Control Designers, Control Developers and Application Developers to work independently of one another.
• Create a single Silverlight Control library of reusable Custom and User Controls, each with customized Look-and-feel.
• Look-and-Feel of each control needs to be "baked in" so that they can be used "as is" by our Application.
• Controls should still be open to further styling and customization by the Application Developer at the application layer.

Requirements
VS 2008 SP1, .net 3.5 SP1, Silverlight Tools with RC0 builds + SP1. For download locations, see my previous post here.

Setup
• a Silverlight Class Library called YControlsLib
• a SilverlightApplication called YControlsDemo
• allowed VS2008 to automagically generate a YControlsDemo.Web asp.net project to host YControlsDemo project

Download The Solution
The solution is available here for download.

YControlsLib
Here, I will wear the Control Developer and Control Designer hats. The simplest control to play with, in my opinion, is the Button control.

Controls can fall into three categories:
1. Combine two or more basic controls into a single control
2. Enhance a single, existing control
3. Create something completely new from scratch

My custom Button resides in the 2nd category.

Because I am simply enriching an existing control I decided to subclass Button and create my own Custom Control, called Ybutton. I will customize Button's look-and-feel. Idea is to be able to use Ybutton with its custom style out-of-the-box in my Application, without the need to override the Button's template.

Although subclassing does not always make sense, I do feel that there are clear benefits in this case:
• For Application Developer, encapsulates control functionality and branding
• Clearly differentiates your organization's control from the default
• Allows you to customize certain behaviors of the control without modifying the original
• Provides some protection against changes to the original control. Subclassing or Wrapping (the former in this case) is perhaps an enterprise-friendly approach.

I started with a simple .cs file without any XAML files. This is what we can refer to as a lookless control stub.

YButton.cs
namespace YControlsLib
{
public class YButton : Button
{
public YButton()
{
this.DefaultStyleKey = typeof(YButton);
}
}
}

DefaultStyleKey is important. This is the only line of custom code needed to bind my custom Button to my custom Template. This template is defined in generic.xaml.

Themes/generic.xaml
As per the Breaking Changes document, generic.xaml needs to reside within the Themes folder. Your Application will not recognize the template binding if this file lives anywhere else.

There is no template in VS for creating this file. I just create a text file and modify its extension. Also, it has to compiled as a Resource (not an Embedded Resource) for runtime and Blend to know what to do with it. More on Blend later.

Here is the basic layout:



YControlsDemo/Page.xaml
Page.xaml is authored by the Application Developer. All Controls required for this project are made available to the App Developer via Silverlight's Default Controls library and the Controls provided by the YControlsLib dll. For simplicity, the YControlLib project is simply referenced from YControlsDemo.


Page.xaml is the typical UserControl which defines one View from our Application. Our App is effectively just a Demo of three Controls:
i. Default Button
ii. My custom button, Ybutton
iii. Ybutton with a tweak from App Developer

Page.xaml only contains:
 <UserControl x:Class="YControlsDemo.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ycontrols="clr-namespace:YControlsLib;assembly=YControlsLib">
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal">

<!-- (i) This is just a plain ol' boring Button -->
<Button Width="100" Height="45" Content="Button"/>

<!-- (ii) YButton inherits everything from above Button but also contains it's own
template. Because the custom template is inherent to the control, App
Developer can use it as is -->
<ycontrols:YButton Width="100" Height="45" Content="YButton"/>

<!-- (iii) This is a YButton with a custom Style that App Owner defines in App.xaml.
Useful for disobeying your company's Branding guidelines -->
<ycontrols:YButton Width="100" Height="45" Content="Ybutton Style"
Style="{StaticResource TweakedYButtonStyle}"/>

<!-- (iv) This is a YButton with a custom DataTemplate -->
<ycontrols:YButton Width="100" Height="45"
ContentTemplate="{StaticResource YButtonCustom}"/>
</StackPanel>
</UserControl>

Since we have not yet completed Ybutton with it's custom Template nor defined any custom Style, our Designer will only show us the default Button:




Back to Themes/generic.xaml
We now need to wear the Control Designer hat. For this, we need to use Expression Blend. The SP1 Preview still does not handle Generic.xaml too well. Because my YButton Control is lookless, Blend will not understand that I want to create a custom template and keep it in Generic.xaml.

For a bit of a work-around, I created a UserControl (similar to Page.xaml) called ControlsForBlendsBenefit.xaml. This goes directly into the YControlLib project. This item will contain a plain Button and my Ybutton.

ControlsForBlendsBenefit.xaml
 <UserControl x:Class="YControlsLib.ControlsForBlend"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300"
xmlns:local="clr-namespace:YControlsLib;assembly=YControlsLib">
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Vertical">
<Button Width="100" Height="45" Content="Button"/>
<local:YButton Width="100" Height="45" Content="YButton"/>
</StackPanel>
</UserControl>
The Button is there so that I can "Edit a Copy" of it's default template within Blend. I will be tethering this modified copy to YButton, making it the Default Template.

Now, I right-click on the xaml file and "Open in Expression Blend..."



Now, Right-Click on Button and select to "Edit a Copy…" of the Button's template.




We'll be doing moving generated content around anyway, so where we put the Copy of Button's default template is not very important. I'll put it within ControlsForBlendsBenefit.xaml.



Notice that the dialog below is asking me for a Name/Key. This is the Key that allows an Application view to specify a Style={StaticResource ButtonStyle1}. This is where things get a bit confusing. Silverlight provides two ways of overriding Look-and-Feel of controls. One is through a replacement of the Template itself, or one by simply Key-ing a new Style. The Style can reside within App.xaml or in a more localized location, the UserControl, or even more scoped, within the Control itself. The way that Blend generates this Style, the Style will contain the copy of the Template. My Button will have to use the Style attribute to access it. This is not what we want. But for Blend's sake, we'll work through it this way.

If we peek into the code of ControlsForBlendsBenefit.xaml we'll see something like:


<UserControl x:Class="YControlsLib.ControlsForBlend"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300"
xmlns:local="clr-namespace:YControlsLib;assembly=YControlsLib" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
<UserControl.Resources>
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">

After customizing these pieces from Blend, it is the code block beginning with that will make its way over to Generic Xaml. In fact, we can do so now and continue editing from within generic.xaml. Perhaps, for the final release, the Silverlight team will make working with generic.xaml a bit more straight-forward.

Generic.xaml Revisited
This file will now include a copy of Button's default Template:


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YControlsLib;assembly=YControlsLib">
<Style x:Key="ButtonStyle1" TargetType="Button">

You will notice many prefixes adorning VisualState prooerties in the newly crafted generic.xaml . Visual Studio does not like these. They are relics left behind by Blend. Looks like it is yet another quirk that the Silverlight Team needs to work out. A forum post for this is here: http://silverlight.net/forums/t/23959.aspx. I'll just "Quick Search/Replace" the "vsm:" bits into nothingness.

The last bit of work to complete here is to remove the generated UserControl.Resources and Style markup from the ControlsForBlendsBenefit.xaml. Remember, we are not going for inline styles. We want to override Ybutton's default Template.

If you are switching between VS and Blend, you may need to recompile your Project in VS for the new generic.xaml to properly expose Templates within Resources tab in the upper right corner.

Once Blend reload the project you should now see something like this:




We will be Editing the ButtonStyle1 resource from now on. After selecting the Resource for Edit (right-most button along-side the ButtonStyle1), we can click on the icon in the left-most corner and "Edit the Template" itself.

We should now see all the Parts and States of the Button Template we will be customizing.




I'll simply customize some gradients to give this Button template an overall Orange hue.

Finally, the last step is to apply the Style and Templates to YButton only. This is done by replacing TargetType="Button" with TargetType="local:YButton".

Themes/generic.xaml is now:
 <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YControlsLib;assembly=YControlsLib">
<Style TargetType="local:YButton">
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>

</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:YButton">
<Grid>

</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Editing Styles in App.xaml
After rebuilding the solution, we should now see the following in the ControlsForBlendsBenefit.xaml:


The markup inside is simply:

<UserControl x:Class="YControlsLib.ControlsForBlend"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300"
xmlns:local="clr-namespace:YControlsLib;assembly=YControlsLib" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">

<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Vertical">
<Button Width="100" Height="45" Content="Button"/>
<local:YButton Width="100" Height="45" Content="YButton"/>
</StackPanel>
</UserControl>

Notice, there is no Styling within the View. We have successfully encapsulated the custom template to the YButton Custom Control!

Back to our YControlsDemo
YControlsDemo simply references the YControlsLib as a DLL containing our Custom Controls. The code of our Page.xaml is still:
 <UserControl x:Class="YControlsDemo.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ycontrols="clr-namespace:YControlsLib;assembly=YControlsLib">
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal">
<Button Width="100" Height="45" Content="Button"/>
<ycontrols:YButton Width="100" Height="45" Content="YButton"/>
<ycontrols:YButton Width="100" Height="45" Content="YButton2"
Style="{StaticResource YButtonStyle}"/>
</StackPanel>

</UserControl>
But now the Preview shows us:





I will simply rotate the Button a bit and change the Background gradient. My end-result is:




Extra Credit: Editing the Ybutton's DataTemplate within App.xaml
The last tweak I will introduce is one introducing DataTemplate. Plain ol' Button has a simple TextBlock at its heart. What if I want something a bit more expressive while retaining the overall Template and Style of the Ybutton?

Solution is to use Blend to only Edit the DataTemplate of the 4th Control.



To keep things simple, I only introduced a two-column Grid layout with an Elipse in the first Column and a static TextBlock in the second Column.

Resulting manifestation of YButton is:



App.xaml
The resulting App.xaml in YControldDemo is then:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="YControlsDemo.App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:YControlsLib="clr-namespace:YControlsLib;assembly=YControlsLib" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
>
<Application.Resources>

<DataTemplate x:Key="YButtonCustom">
<Grid ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Ellipse Grid.Row="0" Grid.Column="0" Margin="5,0,5,0" HorizontalAlignment="Stretch">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#FFF4F3ED"/>
<GradientStop Color="#FFE27259" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<TextBox Text="Click Me" TextWrapping="Wrap" Grid.Row="0" Grid.Column="1" Background="{x:Null}" BorderBrush="{x:Null}"/>
</Grid>
</DataTemplate>

<Style x:Key="YButtonStyle" TargetType="YControlsLib:YButton">
...
</Style>

</Application.Resources>
</Application>

Done.
Rebuilding the solution, our Silverlight RC0 Demo App looks like:




Conclusion
In this post, I've attempted to exercise three of multiple roles commonly played on a large project:
1. Control Designer
2. Control Developer
3. Application Developer

Using both Visual Studio 2008 SP1 + Silverlight Tools as well as Expression Blend RC0 Preview, I subclassed a regular Button so as to completely encapsulate a custom Look-and-Feel for my version of the Button without having to re-instrument the entire control. Through the use of Generic.xaml in the Themes folder of my Control Lib, I was able to specify my custom Template and Styling for my button while giving the Application Developer a simple Control, YButton.

I also submitted a bit of extra credit by demonstrating how Application Developers retain flexibility to further modify Data Templates and the Content Templates of Custom Controls within App.xaml.

So what is App.xaml vs Generic.xaml. Generic.xaml is a compiled Resource. Silverlight is hardwired to look for default Templates within Generic.xaml. It is ideal for providing custom templates for a Control Lib. It will travel with the Control Lib without the need for further intervention by the Application Developer. It permits custom control look-and-feel out-of-the-box. App.xaml is simply a scoping mechanism for providing nuance Styling and Templates for the given Application only. To port Styles and Templates within App.xaml to other application, one would have to copy over App.xaml itself.

Hope this helps shed additional light on Custom Controls, the Silverlight 2 RC0 way! If you wish to download the entire Project, the zip archive is available here.

Related Articles from fellow Bloggers
I've spent much time reading other great Blog entries. Some of them are below:

Sunday, September 28, 2008

Silverlight 2 RC0 is here!

RTM is a month away

Silverlight 2 RC0 is here, or rather here, which means that RTM is less than a month away! Developers are asked to gain a head start on remediating Beta 2 applications. For convenience, the links and Breaking Changes details are reproduced here.

Silverlight 2 RC0 Tools for Developers

Breaking Changes Since Beta 2

This topic discusses the changes made to the Silverlight runtime and Silverlight tools between the Microsoft Silverlight 2 Beta 2 and the final release of Silverlight 2. The changes discussed in this article are focused on changes that might cause your older Silverlight-based applications to now fail or behave differently, not on new features/enhancements for this release.

Note Corrections/Additions to this document (if any) are listed here.

Note Applications built with Beta 2 will not run on final runtime builds. End users will see a message informing them that the application was built with an obsolete version of Silverlight. You must rebuild your Beta 2 applications – see here for more information.

Tip Given the large number of API changes, particularly those listed in the Miscellaneous API Changes section, you may want to search this document by using CTRL+F.

Contents:

  1. Get the newest version of Silverlight 2 Tools for Visual Studio 2008. You can get these tools from the SDK or online at Getting Started. You may have to uninstall any old tools before doing this install.
  2. Open your old project (e.g. .csproj file). A dialog will come up notifying you that your project was created with an older version of Silverlight tools and asks you if you want to upgrade your project. Click the Yes button.
  3. Open all of the HTML files and change:
  • The Silverlight MIME type from application/x-silverlight-2-b1 or application/x-silverlight-2-b2 to application/x-silverlight-2.
  • Note: some templates replaced http://go with http://go2. Be sure to search for both.


  • ContentPresenter now derives from FrameworkElement instead of Control

    Who Is Affected: Applications that use ContentPresenter or objects derived from ContentPresenter.

    Summary

    Because ContentPresenter now derives from FrameworkElement, the following properties are no longer exposed by ContentPresenter:

  • Background
  • BorderBrush
  • BorderThickness
  • DefaultStyleKey
  • FontFamily
  • FontSize
  • FontStretch
  • FontStyle
  • FontWeight
  • Foreground
  • HorizontalContentAlignment
  • IsEnabled
  • IsTabStop
  • Padding
  • TabIndex
  • TabNavigation
  • Template

  • In addition, some APIs were removed from ContentPresenter (see ContentPresenter and ContentControl Changes).

    Fix Required

    Remove all these obsolete properties from your ContentPresenter objects, which will likely require you to re-work some of your code to restore your previous UI rendering.

    Layout Rendering Slightly Changed

    Who Is Affected: All content using layout might be rendered slightly differently because layout no longer causes elements to be rendered at sub-pixel locations.

    Summary

    The layout system in Silverlight has been modified to round final measure and arrange values to integers when placing elements on the screen ("pixel snapping"). The result is crisper lines, more consistent rendering look, and fewer rendering artifacts.

    Layout rounding will be *on* by default, but there is a new inherited property on UIElement called UseLayoutRounding that can be set to false if the old layout behavior is desired.

    Note It is possible that this change will affect how your animations render, in which case you might want to set UseLayoutRounding to false.

    Note This change does not affect transforms. If you apply a transform to an element, it may still be rendered at a sub-pixel location.

    Cross domain hosts of Silverlight must set the right MIME type for XAP (application/x-silverlight-app)

    Who Is Affected: Anyone serving Silverlight 2 apps from cross domain:

  • Via a web server that is not IIS7
  • Via a web server where the MIME type for .XAP files is incorrectly configured

    Summary/Fix Required

    When the XAP is served from a different domain than the host HTML page, Silverlight will validate that the MIME type (Content-Type response header) returned on the HTTP response is application/x-silverlight-app.

    Apache (and perhaps other servers) tend to serve unrecognized content as text/plain, and therefore will be affected by this change. You are required to add an entry for the Silverlight XAP MIME type to your .htaccess file -- e.g. AddType application/x-silverlight-app xap.

    Note IIS7 shipped with the right MIME type configurations for Silverlight XAPs. No action is required if you are using IIS7.

    Exceptions now thrown in HttpWebRequest.EndGetResponse()

    Who Is Affected: Silverlight 2 applications that use HttpWebRequest.

    Summary/Fix Required

    For HttpWebRequest:

    Before:

  • Some security exceptions (e.g. cross-scheme violations) were being raised in HttpWebRequest.BeingGetResponse()
  • All other request error conditions were being returned as 404s.

    Now:

  • Error conditions are now raised as exceptions in HttpRequest.EndGetResponse().
    • Request security errors (e.g. requests not allowed by cross domain policy) raise SecurityExceptions

    • Non-successful requests (e.g. those that returned 404s) raise WebExceptions. The WebException.Response is set to HttpStatusCode.NotFound. This is compatible with the desktop.

    Font URI is Restricted to Assembly Resource

    Who Is Affected: Silverlight 2 Beta1 or Beta 2 applications (not Silverlight 1.0 applications) that reference fonts (or zip of fonts) via the URI syntax in the Control.FontFamily, TextBlock.FontFamily or Glyphs.FontUri attributes and where the fonts are not embedded within the assembly (dll) of the control or application.

    Fix Required

    You can specify a font (or in some cases a zip of fonts) in URI format via the Control.FontFamily, TextBlock.FontFamily and the Glyphs.FontUri attributes. If you are, you will need to ensure your font is marked as a "resource" in the project system.

    Browser.HtmlElementCollection replaced with by Browser.ScriptObjectCollection

    Who Is Affected: Silvlierlight 2 Beta 2 applications using HTML bridge's HtmlElementCollection will break. The type has been replaced with a new type: ScriptObjectCollection.

    Summary

    The System.Windows.Browser.HtmlElementCollection type was changed to ScriptObjectCollection. All previous references to HtmlElement on the collection have been changed to instead reference ScriptObject. Other areas of the HTML bridge that previously used HtmlElementCollection (i.e. HtmlElement.Children) have been switched to instead return a ScriptObjectCollection. Note that if you retrieve an item from the new ScriptObjectCollection that actually is an HtmlElement, you can still cast the return value back to an HtmlElement.

    The specific benefit from this change is that across all browsers you can now access both element, and non-element, DOM nodes contained in a node collection. We made this change because there is no consistent cross-browser implementation of an HtmlElement-specific collection type.

    Fix Required

    Change existing references to HtmlElementCollection to ScriptObjectCollection. If your existing code was working with HtmlElement return values you will need to explicitly cast the items returned from a ScriptObjectCollection to an HtmlElement. Since the collection type is now ScriptObjectCollection it is likely that on different browsers the ordinality of the resulting collection will also change. Any code that was relying on fixed offsets into the collection may need to be changed to account for non-element nodes (e.g. text nodes such as whitespace, etc…) in the collection.

    Beta 2

    [c#]

    HtmlElement myHtmlElement = someOtherHtmlElement.Children[5];

    Release

    [c#]

    HtmlElement myHtmlElement = (HtmlElement)someOtherHtmlElement.Children[5]; //assuming the desired element is still at offset 5

    Exceptions When Changing Some Properties on an Active Animation

    Who Is Affected: Silverlight 1.0 and 2.0 applications that change properties on active animations.

    Summary

    When you change one of the properties listed below on an active Storyboard, an exception is raised at runtime with this message: "Operation is not valid on an active Animation or Storyboard. Root Storyboard must be stopped first."

    The list of properties that cannot be modified on an active animation or Storyboard are listed below:

    Attached Properties

  • Storyboard.TargetNameProperty
  • Storyboard.TargetPropertyProperty

    Properties on derived classes from Timeline of a collection type

  • Storyboard.Children (you cannot add/remove animations from an active storyboard)
  • ColorAnimationUsingKeyFrames.KeyFrames
  • DoubleAnimationUsingKeyFrames.KeyFrames
  • PointAnimationUsingKeyFrames.KeyFrames
  • ObjectAnimationUsingKeyFrames.KeyFrames

    Make sure you stop the Storyboard before changing one of these properties. You can do this by using the Storyboard.Stop method.

    System.Windows.Controls.Extended.dll renamed to System.Windows.Controls.dll

    Who Is Affected: Anyone who uses the extended controls (Calendar, DatePicker, TabControl and GridSplitter).

    Fix Required

    Change all references from System.Controls.Extended to System.Windows.Controls and recompile your application.

    VisualStateManager Changes

    Who Is Affected: Silverlight 2 applications that use VisualStateManager.

    Summary

    VisualTransition.Duration has changed to VisualTransition.GeneratedDuration. This value will now only affect the generated transitions, and not the VisualTransition.Storyboard.

    Example:

    In the below XAML, the VSM generated animations for the Pressed-> Normal transition will be created with 1 second durations. The explicit transition Storyboard with its blue ColorAnimation will still be 2 seconds.

    [xaml]

    <vsm:VisualStateGroup x:Name="CommonStateGroup">

    ...

    <vsm:VisualStateGroup.Transitions>

    ...

    <vsm:VisualTransition From="Pressed" To="Normal" GeneratedDuration="0:0:1">

    <Storyboard>

    <ColorAnimation Storyboard.TargetName="MainRect" Duration="0:0:2"

    Storyboard.TargetProperty="Fill" SpeedRatio="2" To="Blue"/>

    </Storyboard>

    </vsm:VisualTransition>

    </vsm:VisualStateGroup.Transitions>

    </vsm:VisualStateGroup>

    VisualStateManager.CustomVisualStateManager should be set on the root visual of the ControlTemplate or UserControl, not the Control/UserControl itself. In the example below, the custom visual state manager is set on the Grid, the ControlTemplate's root visual.

    [xaml]

    <ControlTemplate TargetType="local:CheckBox">

    <Grid x:Name="RootElement" HorizontalAlignment="Center"

    VerticalAlignment="Center" Background="Transparent">

    <vsm:VisualStateManager.CustomVisualStateManager>

    <local:MyVisualStateManager>

    </vsm:VisualStateManager.CustomVisualStateManager>

    ...

    </Grid>

    </ControlTemplate>

    KeyDown Sent Synchronously

    Who Is Affected: If you previously have been doing operations in the KeyDown event that could cause reentrancy into the Silverlight control, such as calling into the HtmlPage.Window.Alert function, this will no longer be supported.

    Summary

    We switched over our keyboard handling for character input to use the concept of the WM_CHAR windows message. This is used for TextBox/PasswordBox text entry to enable scenarios such as entering AltGr keystrokes. In order for us to do this, the KeyDown event had to be sent synchronously for managed code.

    MeasureOverride/ArrangeOverride on Canvas Now Sealed

    Who Is Affected: Silverlight 2 Beta 2 Applications that use MeasureOverride and ArrangeOverride on Canvas.

    Summary

    MeasureOverride and ArrangeOverride virtual methods on Canvas are sealed. These methods were already sealed for Grid and StackPanel. Any custom panel that requires its own layout logic should subclass Panel.

    UriTypeConverter moved to System.dll

    Who Is Affected: Silverlight 2 managed code referencing the UriTypeConverter class.

    Fix Required

    UriTypeConverter was moved from System.Windows.Controls.dll to System.dll where it resides on the desktop framework. Applications that reference it just need to be recompiled.

    HtmlPage.UnregisterScriptableObject Removed

    Who Is Affected: Those using HtmlPage.UnregisterScriptableObject.

    Fix Required

    Alternative to using HtmlPage.UnregisterScriptableObject, developers can now re-use the same script registration key for RegisterScriptableObject. This allows developers to change the underlying managed object associated with a scriptable entry point.

    RenderingEventArgs Changes

    Who Is Affected: Silverlight 2 managed code referencing the RenderingEventArgs class.

    Summary

    The following changes have been made to class RenderingEventArgs

  • RenderingEventArgs is moved from System.Windows to System.Windows.Media
  • RenderingEventArgs.ctor() is now internal
  • System.Windows.RenderingEventHandler has been removed.

    ContentPresenter and ContentControl Changes

    Who Is Affected: Silverlight 2 managed code that uses either the ContentPresenter or ContentControl classes.

    Summary

    The following properties were removed from ContentPresenter and ContentControl.

  • TextAlignment
  • TextDecorations
  • TextWrapping

    Removal of FileDialogFileInfo Type and OpenFileDialog.SelectedFile(s) Properties

    Who Is Affected: Silverlight 2 applications which use the OpenFileDialog.

    Summary

  • The System.Windows.FileDialogFileInfo type is being removed. Its functionality is now being exposed via its base System.IO.FileInfo type to transparent code within Silverlight's sandbox.
  • System.Windows.Controls.OpenFileDialog has a couple properties which consume and expose FileDialogFileInfo. They were modified to return the FileInfo type.
  • In addition, the property names SelectedFile and SelectedFiles were also changed to File and Files.

    Fix Required

    Beta 2

    [c#]

    // Returns a File object for the selected file. If multiple files are selected, returns the first selected file

    public FileDialogFileInfo SelectedFile { get; }

    // Returns a collection of File objects for the selected files

    public IEnumerable<FileDialogFileInfo> SelectedFiles { get; }

    Release

    [c#]

    // Returns a File object for the selected file. If multiple files are

    // selected, returns the first selected file

    public FileInfo File { get; }

    // Returns a collection of File objects for the selected files

    public IEnumerable<FileInfo> Files { get; }

    Sample usage of OpenFileDialog with this change:

    [c#]

    openFileDialog = new System.Windows.Controls.OpenFileDialog();

    openFileDialog.Multiselect = false;

    openFileDialog.Filter = "Text Files (*.txt)|*.txt|All files (*.*)|*.*";

    bool? retval = ofd.ShowDialog();

    if (retval != null && retval == true) {


    // Get the filename

    string filename = openFileDialog.File.Name;

    // Open the file

    System.IO.Stream filestream = openFileDialog.File.OpenRead();

    // Do something with the filestream

    // Close it

    }

    Removal of FullAccess Option on the ExternalCallersFromCrossDomain attribute in the Silverlight 2 application manifest

    Who Is Affected: Only Silverlight 2 applications that use this combination of features:

  • XAP deployed on a different domain than the host HTML page, and
  • with application manifest (AppManifest.xaml) specifying ExternalCallersFromCrossDomain="FullAccess" on the root element are affected.

    Summary

    The ability for arbitrary scripts to walk the element tree, register for and get notified on events, and use the Silverlight 1.0 Downloader from script has been curtailed in a cross-domain app deployment scenario. The application manifest previously supported the ability for app author to designate the ExternalCallersFromCrossDomain attribute with the values NoAccess (default in cross-domain), ScriptableOnly and FullAccess. Support for the FullAccess option has been removed.

    Many of the purposes you would have relied on the FullAccess option can now be fulfilled via the Scriptable object feature, with minor additional work on your part.

    KeyFrameCollection Changes

    Summary and Fix

    Virtual methods Add, Contains, Indexof, Insert, Remove, get_Item, set_Item are no longer declared on the following collections:

  • ColorKeyFrameCollection.
  • DoubleKeyFrameCollection
  • ObjectKeyFrameCollection
  • PointKeyFrameCollection
  • PointKeyFrameCollection
  • StrokeCollection

    Request stream must be closed before calling HttpWebRequest.BeginGetResponse()

    Who Is Affected: Silverlight 2 applications that use HttpWebRequest.BeginGetResponse().

    Summary

    You must close the request stream on an HttpWebRequest before calling BeginGetResponse(). Previously BeginGetResponse() would close an open request stream.

    HtmlWindow references on Safari/Mac will no longer evaluate to true

    Who Is Affected: Code that uses System.Windows.Browser.HtmlWindow and that expects two HtmlWindow references pointing at the same DOM window to evaluate to true will now return false when running on Safari 2 or Safari 3 on Mac.

    Summary

    For example:

  • Create a page with one iframe
  • Use the bridge to get two references to the iframe:

    HtmlWindow myWin = document.GetElementById("myIframe");

    HtmlWindow myWin2 = document.GetElementById("myIframe");

  • With the change the following comparison will now return false on Safari 2/3 Mac:

    bool areEqual = (myWin == myWin2);

    Address property removed from all WebClient EventArg classes

    Fix Needed

    If you were depending on the Address property, you can work around this breaking change in the following way:

    Beta 2

    [c#]

    void Callback(object sender, DownloadStringCompletedEventArgs args)

    {

    DebugPrint(args.Address.ToString());

    }


    void MakeCall(Uri uri, object userState)

    {

    webClient.DownloadStringAsync(uri, userState);

    }

    Release

    [c#]

    class DownloadState

    {

    public DownloadState() {}

    public Uri Address;

    public object ActualUserState;

    }

    void Callback(object sender, DownloadStringCompletedEventArgs args)

    {

    DownloadState userState = (DownloadState)args.UserState;

    DebugPrint(userState.Address.ToString());

    }

    void MakeCall(Uri uri, object userState)

    {

    Uri absoluteUri = uri;

    if (absoluteUri.IsAbsoluteUri == false)

    {

    absoluteUri = new Uri(new Uri(webClient.BaseAddress), absoluteUri);

    }

    DownloadState downloadState = new DownloadState();

    downloadState.Address = absoluteUri;

    downloadState.ActualUserState = userState;

    webClient.DownloadStringAsync(uri, downloadState);

    }

    Constructors Made Internal

    Summary

    You can no longer create the objects listed below because their associated constructors have been made internal:

  • SizeChangedEventArgs
  • TextChangedEventArgs
  • DownloadProgressEventArgs
  • ExceptionRoutedEventArgs
  • KeyEventArgs
  • MouseButtonEventArgs
  • MouseEventArgs
  • StartupEventArgs
  • Expression
  • GeneralTransform
  • Geometry
  • ImageSource
  • PathSegment
  • SetterBase
  • Transform
  • BindingExpressionBase
  • InputMethod

    Exception type change for System.Xml exception type

    Summary

    In the methods/constructors shown below, we will no longer be checking for null arguments. As a result, the usage of null arguments will result in a NullReferenceException. In previous builds of Silverlight, use of a null argument would result in an ArgumentNullException being thrown. There is no change in functionality, just the type of exception that is being thrown.

  • XmlReader.IsName method
  • XmlReader constructor
  • XmlReader.MoveToAttribute method
  • XmlReader:IsNameToken method
  • XmlNamespaceManager constructor
  • XmlReader.Nametable.Add method
  • XmlReader.Nametable.Get method
  • XmlCharCheckingWriter.WriteQualifiedName method
  • XmlCharCheckingWriter.WriteDocType method
  • XmlConvert.ToBoolean method
  • XmlConvert.ToDouble method
  • XmlConvert.ToSingle method
  • XmlConvert.ToDateTime method

    Cannot create classes in XAML that do not have accessible constructors

    Summary

    Certain classes that were defined by the Silverlight runtime were creatable in XAML, even though they did not have an accessible constructor. With this change, you can no longer instantiate those classes in XAML.

    These classes (which only have internal constructors) can no longer be created in XAML:

  • TriggerCollection
  • InlineCollection
  • RowDefinitionCollection
  • ColumnDefinitionCollection
  • RoutedEventARgs
  • MouseButtonEventArgs
  • KeyEventARgs
  • ErrorEventArgs
  • UIElementCollection
  • Downloader
  • InternalWebRequest
  • MultiScaleSubImageCollection
  • MediaAttribute
  • MediaAttributeCollection
  • ExceptionROutedEventArgs
  • DownloadProgressEventArgs
  • StartupEventArgs
  • TextBoxBase
  • TextBoxView
  • TextChangedEventArgs
  • RuntimeHostEventArgs
  • SizeChangedEventArgs
  • RenderingEventArgs
  • ItemCollection
  • CorePropertyChangedEventArgs
  • IsEndabledChangedEventARgs
  • TypeProxy
  • ManagedObjectReference
  • AutomationPropertiesEnum
  • DependencyPropertyProxy

    Get AG_E_UNKNOWN_ERROR in Silverlight 2 but not in Silverlight 1

    Summary

    In previous versions of Silverlight, when media failed because a media file was not available, a MediaFailed event was fired but if the MediaFailed event was not handled by the developer, the end user would not be notified of the failure. Now when a handler is not hooked up to the MediaFailed event, the error bubbles up to the default OnError handler of the plug-in and AG_E_UNKNOWN_ERROR is displayed to the user.

    Fix Required

    Attach the MediaFailed event to your MediaElement objects and handle errors as appropriate.

    Platform looks for generic.xaml as a resource at themes/generic.xaml

    Summary

    The platform now looks for the generic.xaml resource dictionary as an assembly resource in the "themes" directory rather than the root directory.

    Fix Required

    Move your generic.xaml resource underneath the "themes" folder under ControlLib in Solutions Explorer in Visual Studio.

    HTTP Polling Duplex OM Changes and Reengineering

    Who Is Affected: This will impact anyone using the HTTP Polling Duplex channel.

    Summary

  • PollTimeout setting on the server side (PollingDuplexHttpBinding and PollingDuplexBindingElement) has been renamed to ServerPollTimeout
  • PollTimeout setting on the PollingDuplexBindingElement (client side) has been renamed to ClientPollTimeout.
  • PollTimeout setting on the PollingDuplexHttpBinding (client side) has been cut. In most scenarios, it should not be necessary to change this. If a change is necessary, it can be achieved through the ClientPollTimeout on the PollingDuplexBindingElement.
  • Client-side support has been cut from the non-Silverlight (server-side) polling duplex assembly (i.e. BuildChannelFactory will throw a NotSupportedException). That is, in RTM, the client side for polling duplex must be Silverlight (and the server side must be the regular .NET Framework, but this restriction was already in place in Beta2).
  • Default timeouts have been changed for the Duplex channel. For most common scenarios, the new out-of-the-box defaults should be appropriate and there is no need to change them.
  • An error (404) on a polling request will cause the duplex channel to fault.
  • Various invalid messages used to be ignored by the Duplex stack but will now be rejected.
  • If any HTTP error (404,500,…) is encountered during a SOAP call, a CommunicationException is now thrown instead of a ProtocolException.

    Breaking change to Silverlight native hosting IXcpControl COM interface

    Who Is Affected: Applications that host Silverlight 2 natively via its COM APIs.

    Summary

  • The following splash screen related properties added to IXcpControl interface are being broken out and being moved to a new IXcpControl2 interface:
  • get_OnSourceDownloadComplete
  • get_OnSourceDownloadProgressChanged
  • get_SplashScreenSource
  • put_OnSourceDownloadComplete
  • put_OnSourceDownloadProgressChanged
  • put_SplashScreenSource

    In addition, the LoadRuntime function is also being moved to IXcpControl2.

    Content-Type is allowed on cross domain request by default

  • Summary

    Both supported cross domain policy files (crossdomain.xml, clientaccesspolicy.xml) no longer need to explicitly allow the Content-Type request header. The Content-Type header is always settable on POST xdomain requests, as long as the request itself is allowed by a cross domain policy file.

    In addition, the LoadRuntime function is also being moved to IXcpControl2.


    Fix Required

    Previously you needed to specify Content-Type in the headers whitelist. Now, Content-Type is always allowed, so the bolded "Content-Type" attribute value is no longer required just for setting the Content-Type (see below).

    clientaccesspolicy.xml

    Old version that explicitly listed Content-Type as settable. (This file still works in SL2 RTM.)

    [xaml]

    <?xml version="1.0"?>

    <access-policy>

    <cross-domain-access>

    <policy>

    <allow-from http-request-headers="Content-Type, SOAPAction">

    <domain uri="*"/>

    </allow-from>

    <grant-to>

    <resource include-subpaths="true" path="/"/>

    </grant-to>

    </policy>

    </cross-domain-access>

    </access-policy>

    New version that still allows Content-Type to be set

    [xaml]

    <?xml version="1.0"?>

    <access-policy>

    <cross-domain-access>

    <policy>

    <allow-from http-request-headers="SOAPAction">

    <domain uri="*"/>

    </allow-from>

    <grant-to>

    <resource include-subpaths="true" path="/"/>

    </grant-to>

    </policy>

    </cross-domain-access>

    </access-policy>

    crossdomain.xml

    Old version that explicitly listed Content-Type as settable. (This file still works in SL2 RTM.):

    [xaml]

    <?xml version="1.0"?>

    <cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd">

    <allow-access-from domain="* " />

    <allow-http-request-headers-from domain="* " headers="Content-Type, SOAPAction" secure="true" />

    </cross-domain-policy>

    New version that still allows Content-Type to be set:

    [xaml]

    <?xml version="1.0"?>

    <cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd">

    <allow-access-from domain="* " />

    <allow-http-request-headers-from domain="* " headers="SOAPAction" secure="true" />

    </cross-domain-policy>

    Enforcing delegate type check when two delegate objects are combined

    Who Is Affected: Code that bypass the delegate type check in Delegate.Combine by calling MulticastDelegate.CombineImpl directly.

    Fix Required

    If you want to combine two delegate objects they should be of the exact same delegate type.

    Miscellaneous API Changes

  • UIElement.HitTest method has moved to the VisualTreeHelper class and renamed to VisualTreeHelper.FindElementsInHostCoordinates.
  • Moved DependencyPropertyChangedEventHandler delegate type from System.Windows.Controls to System.Windows namespace.
  • Control.IsTabStop defaults to true. Now, all Control derived classes (directly or indirectly) have IsTabStop set to true except, UserControl, HyperlinkButton, ScrollViewer and ListBox.
  • WebHeaderCollection.Keys property was replaced with the AllKeys property.
  • WebHeaderCollection.Headers property was renamed to Keys.
  • WebRequest.RegisterPrefix() now returns false in failure cases per the interface contract from the desktop framework rather than throwing an exception.
  • WebResponse.Dispose(bool explicitDisposing) was removed.
  • Deployment.PartProperty is now read only.
  • Deployment.EntryPointAssemblyProperty is now read only.
  • Deployment.EntryPointTypeProperty is now read only.
  • Deployment.RuntimeVersionProperty is now read only.
  • Deployment.ExternalCallersFromCrossDomainProperty is now read only.
  • Thumb.IsDragging is now read only.
  • Slider.IsFocused is now read only.
  • ButtonBase.IsFocused is now read only.
  • ButtonBase.IsMouseOver is now read only.
  • ButtonBase.IsPressed is now read only.
  • ToolTipService.GetToolTip is now private.
  • IRawElementProviderSimple is now sealed and has a private default constructor.
  • Setter.PropertyProperty is now internal. Please use the CLR property instead of the DependencyProperty.
  • Slider.UpdateTrackLayout() is now internal.
  • Slider.OnOrientationChanged() is now internal.
  • Slider.OnIsFocusChanged(DependencyPropertyChangedEventArgs e) is now internal.
  • ComboBox.get_IsSelectionActive() is now internal.
  • ComboBox.ScrollIntoView(Int32 index) is now internal.
  • ComboBox.get_SelectionBoxItemTemplate() now returns System.Windows.DataTemplate.
  • PasswordBox.SelectionChanged is now private.
  • MouseEventArgs.Handled was moved to MouseButtonEventArgs.
  • RenderTargetBitmap was renamed to HostingRenderTargetBitmap and moved from System.Windows.Media.Imaging to namespace System.Windows.Interop.
  • AutomationPeer constructor is now protected.
  • TriggerActionCollection.Item now takes System.Windows.TriggerAction instead of System.Windows.Media.Animation.BeginStoryboard.
  • TriggerCollection.Item now takes System.Windows.TriggerBase instead of System.Windows.EventTrigger.
  • RoutedEventArgs.Source was renamed to OriginalSource and is now read-only.
  • ITableItemProvider and ITableProvider are now derived from IGridItemProvider and IGridProvider.
  • The KeyboardNavigation class is now internal.
  • ColumnDefinitionCollection constructor was made internal.
  • InlineCollection constructor was made internal.
  • ItemCollection constructor was made internal.
  • RowDefinitionCollection constructor was made internal.
  • UIElementCollection constructor was made internal.
  • TriggerCollection constructor was made internal.
  • Listbox field ListBoxItem._itemsControl is now internal.
  • Ink.Stroke constructor changed to ctor(System.Windows.Input.StylusPointCollection).
  • CanConvertFrom(Type sourceType) changed its signature to CanConvertFrom(ITypeDescriptorContext context, Type sourceType).
  • CanConvertTo(Type destinationType) changed its signature to CanConvertTo(ITypeDescriptorContext context, Type destinationType).
  • ConvertFrom(object value) changed its signature to ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value).
  • ConvertFromString(string text) now is ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) where value of type string.
  • ConvertTo(object value, Type destinationType) changed its signature to ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType).
  • ConvertToString(object value) now is ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) with destinationType of type string.
  • ItemCollection constructor is no longer available so any code that tries to instantiate an ItemCollection directly will no longer compile. This class is supposed to be instantiated only within ItemsControl.
  • ContentPresenter now derives from FrameworkElement instead of Control.
  • Control.OnIsEnabledChanged was removed. Now use IsEnabledChanged for extended controls.
  • DownloadProgressEventHandler was removed.
  • The following converters were removed:
    • TextDecorationCollectionConverter
    • FontStretchConverter
    • FontStyleConverter
    • FontWeightConverter
    • FontFamilyConverter