How many GB’s = 6oz?

27 08 2009

Some things can just make me smile for a week. It doesn’t happen a lot but when it happens it is like drinking nectar of the gods ;)

Today I had one of these moments when I received an email from one of my co-workers with in it a link to this forums question on the Microsoft answers forum:

http://social.answers.microsoft.com/Forums/en-US/vistahardware/thread/720108ee-0a9c-4090-b62d-bbd5cb1a7605

The questions is from January, but for all of you who missed it, this is an incredibly fun read. Also be sure to read all the replies, with mathematical equations explaining the GB to Pounds ratio’s trough the use of mathematical equations by the XVIIII century scholar Lineus Torvaldus.

And if you have anything to add to the discussion please continue the discussion in the comments below.

Have fun reading!

-Robertjan



Silverlight & Expression Blend 3

11 07 2009

Yesterday, there was the long awaited release of Silverlight 3 and Expression Blend 3. So now we can finally bring all the new and exciting things onto live environments, and share it with the world: See the Light!

For those of you who haven’t had the time to follow the Beta, Silverlight 3 brings a wealth of new features features:

Blend 3 also has gone trough a major update, some of the major improvements are:

Over the next few weeks I will write about each of these features, and show how they can impact your development.

All the downloads can be found here.

Have fun playing!

-Robertjan Tuit



No Debugging after converting solution to VS 2010 and Silverlight 3

29 06 2009

Just a quick post to hopefully save a lot of other people the trouble I just went through.

I had a Silverlight 2 and Web solution in VS2008 and converted it to VS2010 and Silverlight 3.

After this conversion a setting is removed from the properties of the Web project: Silverlight Debugging.

image image

This of course disables all debugging with the projects, and sent me on a wild goose chase to all kinds of interesting articles trying to fix debugging with Silverlight.

And of course, all I had to do was enable Silverlight debugging again on the Web project :) Hopefully this will save you the day I lost trying to solve this problem.

-Robertjan Tuit



MSDN Redesign

6 06 2009

Since joining MSDN I have been very busy doing some awesome new stuff. The last couple of months have been like a trip on a high speed train, on the roof whileMSDN_TRAM_HOME juggling 3 melons and tweeting about it at the same time.

Of course most of the things we are doing we have to keep under wraps, so I have not really had the opportunity to blog about what we are doing.

But there are people at Microsoft who really stand on their own, and try to break some of the public barriers. One of them is Scott Hanselman, who is working closely with the team on our efforts to bring a new look and feel to MSDN.

And a couple of hours ago, he decided to share some of the new ideas with the world. Nice!

So have a look at some of the very early designs, and let us know what you think:

http://www.hanselman.com/blog/MSDNUpdatesAndRFCForYou.aspx

- Robertjan Tuit

 

Technorati Tags:


Silverlight 2 dynamic assembly loading - Part 2

6 03 2009

In this article:
- Unpacking and loading the assemblies.
- Direct & Deferred Loading
- Download Progress
In part 1 (click to open) :
- Rebuilding the AppManifest.xaml
- (Re)compressing .xap files with 7zip

A little but later then promised, mostly because I kept building more and more functionality. But here is second part of the Dynamic Assembly Loading. Click here for part 1.

In part 1 we rexapped out applications to meet our requirements, now let’s start loading the application, the custom xaml and the referenced assemblies. We start out with the solutions created in part 1, click here to download it.

ReferencedAssemblies.xaml

To reference and handle the data while loading we create a ReferencedAssembly class looking like this:

public enum ReferencedAssemblyStates { None, Loading, Error, Done };

public class ReferencedAssembly

{

    public ReferencedAssemblyStates State;

    public long ByteSize;

    public long ByteSizeLoaded;

    public double PercentLoaded;

    public string Name;

    public Uri Uri;

    public EventHandler Loaded;

    public Exception Error;

    public AssemblyPart AssemblyPart;

    public LoadingTypes loadingType = LoadingTypes.Direct;

}

Then we load our custom created ReferencedAssemblies.xaml from the Application Resource Stream, in the project this is done when you access the getter of the ReferencedAssemblies property:

var xmlReader = XmlReader.Create(

    Application.GetResourceStream(

        new Uri("ReferencedAssemblies.xaml", UriKind.Relative)

        ).Stream

    );

And use the XamlReader to put the data in our class:

while (xmlReader.ReadToFollowing("ReferencedAssembly"))

{

    // Read Name & Source and Size

    xmlReader.MoveToAttribute("Name");

    var name = xmlReader.Value;

    xmlReader.MoveToAttribute("Source");

    var uri = new Uri(Application.Current.AbsolutePath() + xmlReader.Value, UriKind.Absolute);

    xmlReader.MoveToAttribute("ByteSize");

    var byteSize = long.Parse(xmlReader.Value);

 

    // Create a new ReferencedAssembly class and set values

    var referencedAssembly = new ReferencedAssembly()

        {

            Name = name,

            Uri = uri,

            ByteSize = byteSize

        };

 

    // Add it to the Dictionary

    Current._ReferencedAssemblies.Add(name, referencedAssembly);

}

 

So now we have a list of assemblies, their xap file and their size. (This is a new addition to the ReXapper not done in Part 1). With this list we can load up all our referenced assemblies.

Direct & Deferred Loading

As you might have notice by looking at the code above, I added 2 kind of loading methods: Direct and Deferred.

I added these 2 types to make it possible to load assemblies on demand. This can be very useful when you are building bigger applications.

App.Xaml.cs

Now lets look at what we have to do in our applications. All other code we did so far is a one of, meaning we can just reference it next time. This piece of code needs to be added to every application we wish to use this type of assembly loading.

By default your app.xaml.cs contains the following to initiate your Page:

private void Application_Startup(object sender, StartupEventArgs e)

{

    this.RootVisual = new Page();

}

This should be changed to:

private void Application_Startup(object sender, StartupEventArgs e)

{

    AppAssemblyLoader.Current.LoadReferencedAssemblies(

        new string[] { "System.Xml.Linq" },

        () => this.RootVisual = new Page()

    );

}

What we are doing here is loading the referenced assembly System.Xml.Linq and when it is done call the Page creation method.

Because we also have a MyLibrary.dll in our application this will also be loaded, but this happens in the background. I have added a couple of Events to attach to to monitor what is happening:

public static LoadingDoneEventHandler LoadingDone;

public static LoadingDoneEventHandler LoadingStarted;

public static DownloadProgressChangedEventHandler DownloadProgressChanged;

public static AssemblyDownloadProgressEventHandler AssemblyDownloadProgressChanged;

public static AssemblyStateChangedEventHandler AssemblyStateChanged;

 

If you want to application to start only after every assembly is loaded you just call it like this:

AppAssemblyLoader.Current.LoadReferencedAssemblies(

    () => this.RootVisual = new Page()

);

Loading the Assembly

Loading an assembly is pretty straightforward. First we use a WebClient to get a stream to .xap file.

var wc = new WebClient();

wc.OpenReadCompleted += (sender, e) =>

    {

        LoadAssemblyFromWebResponse(referencedAssembly, e);

    };

 

wc.OpenReadAsync(referencedAssembly.Uri);

Then we take the Result stream and use it load create an AssemblyPart:

private static void LoadAssemblyFromWebResponse(ReferencedAssembly referencedAssembly, OpenReadCompletedEventArgs e)

{

    // Load .xap as StreamResource

    var xap = new StreamResourceInfo(e.Result, null);

    // Get the assembly (.dll) from the .xap StreamResource

    var assemblySri = Application.GetResourceStream(xap, new Uri(referencedAssembly.Name + ".dll", UriKind.Relative));

 

    // Load the stream into a new AssemblyPart

    var assemblyPart = referencedAssembly.AssemblyPart = new AssemblyPart();

    assemblyPart.Load(assemblySri.Stream);

}

 

Luckily Silverlight takes care of everything else. The assembly is added to the Assembly Pool, and when another part of you application requests the assembly it is automatically referenced.

Managed Download Progress

You have the possibility to get the download progress for the total and for every separate assembly. If you would load everything deferred, this would enable you to make a Managed Code Loader.

WrapUp

The end project contains a lot more  code which I won’t talk about here, but if you download the source code you can check it out yourself.

It ended up being a lot more that just the Loader I was planning it to become. But the things that were added, make it very useful for a few other scenario’s as well:

  • Easily separate a Silverlight application into different xap files, making it a good base for bigger applications in SL.
  • Create a managed loader, which is currently impossible with Silverlight.

I hope to have time in the next weeks, to build some demo applications to show off the possibilities.

You can download the finished source code here:
Robertjan Tuit - DynamicAssemblyLoading - Part 2 - Source Code.zip

Of course if you have any questions, ideas or remarks please let me know!

Stay in the Light!

Robertjan Tuit

Technorati:



Silverlight 2 dynamic assembly loading - Part 1

30 01 2009

In this article:
- Rebuilding the AppManifest.xaml
- (Re)compressing .xap files with 7zip
Coming in part 2 (Click to open):
- Loading the assemblies.

Silverlight 2 by default packages all the referenced assemblies into one big xap file. This is a nice for deployment scenarios, but when you have a lot of Silverlight controls, using the same assemblies over and over again, you waste a lot of bandwidth, and user experience drops because of the extra time it takes to load a page.

imageDo not copy local

Some of it can be achieved by setting the “copy local” property of the referenced assemblies to false. This tells the packager not to add them to the .xap file automatically.

Now when the Silverlight application starts in a browser we will have to resolve the “missing” referenced assemblies. I had hoped to use the AppDomain.AssemblyResolve event, but as it seems, this has been marked with the [SECURITY CRITICAL] attribute, which means it can only be used in the .NET framework itself.

Luckily the assemblies are accessed only when needed, so the assembly is only needed when you first access something from the assembly, like a class or method. This means that if we do all the loading in the App.xaml.cs we should be fine. But for this example I will not use this option, so you can put them back to True.

Because I’m Lazy

I am a lazy programmer ;) And I do not want to manually load every assembly for every Silverlight project. I’d rather do some more work now, and save myself (and hopefully you as well) lots of time in the future. And as an added bonus we get some extra compression (+- 20%) in our .xap files, because the normal .xap packager does almost no compression at all. And if you would use the Copy Local option above you would get no compression at all for your referenced assemblies.

To get an idea of what I’m talking about, take a look at the following diagram:

image

What you are seeing above, is the default packaging on the left, and the ReXapped packaging on the right. I also added the size in Kb. To make the difference a bit more drastic, I put 2 images in MyLibrary, which is packaged twice on the left and only once on the right. This also goes for the System.Xml.Linq.dll assembly. The rest of the reduction in size is due to the fact that 7Zip just does better compression. And if you have more then 2 Applications, and you have lots of shared code and images , which in my experience is usually the case, the reduction will be even greater.

ReXapper

Let met start out by saying that the ReXapper name is one I did not think up myself, I have seen it many times already around the web, but why change a good name, right?

The ReXapper is a Console application, which is run After Build on both MySilverlightApplications. It receives the parameters from the build events, and starts ReXapping the applications.

It should be run with the following parameters:
ReXapper.exe [7ZipLocation] [projectName] [projectTargetDir] [silverlightTargetDir]

When used in the After Build event it would be:
$(SolutionDir)ReXapper\bin\debug\ReXapper.exe
$(SolutionDir)7za.exe
$(ProjectName)
$(TargetDir)
$(SolutionDir)DynamicAssemblyLoading.Web\ClientBin

The code for the Rexapper is a bit too big to completely go over right now, but here are a few higlights. You can download the full source code below.

Saving AppManifest.xaml from an XDocument

The AppManifest does not have a xml starting tag. If added, the Silverlight Plugin will fail to load, and of course <?xml is added by default when saving a XDocument :)

The solution is using the XMLWriter with XmlWritersettings having OmitDeclaration = true. Check the SaveXDocumentWithoutXmlDeclaration method in the code.

Changing and not creating the AppManifest

Because I ran into a few problems, creating a new AppManifest from scratch I decided to reuse the ogirinal one and change it to meet the needs.

Lots of Linq and Lambdas

I have become such a fan of Linq and Lambdas that you will see me using it wherever I can, probably even in places where it’s not necessary, I just love to use them :)

Next

Now we have the new xap files, we can run the application and see that they work. Of course you cannot yet use the Referenced assemblies like the System.Linq.Xml and MyLibrary, but because they are not yet used in the code, Silverlight will not trow any errors.

In Part 2, ready hopefully somewhere next week, we will read our custom created ReferencedAssemblies.xaml from our xap, load all the referenced assemblies from their respective .xap files, and use resources from MyLibrary in our Applications.

Click here to download the source code in it’s current state.

Stay in the light!

Robertjan Tuit

Technorati Tags:

*UPDATE: Click here to view part 2



Silverlight 2 Image Tiling

28 01 2009

Silverlight’s big brother WPF has a lot of functionality that you would like to have in Silverlight 2. One of these features is a Tiling Image Brush.

As many of you have probably already found out, it is impossible to create your own brush in Silverlight, because of internal and sealed base classes.

A couple of months a go I was working on a project which required images being tiled across the screen, so I decided to create a tiling control, which takes an image and puts as many as fit the screen into a wrap panel (from the silverlight control toolkit).

Since then I have seen a lot of people asking for this functionality, I though I would share this very simple (user) control. Below is the code, let me know if you have any questions or remarks.

There are still a few improvements you could make to this code. For example determining the width and height of the image automatically. But to keep it simple I left that code out.

The image used in this example is a random one I took from Google image search:

When finished it should look like something like this:

image

In the application: (local namespace should be added to the top of the xaml)

<local:ImageRepeater

   ImageSource="http://ecx.images-amazon.com/images/I/51sghWRypwL._SL75_SS50_.jpg"

   ImageWidth="50"

   ImageHeight="50"/>

UserControl: ImageRepeater.xaml

<UserControl x:Class="ImageRepeater"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"

    >

    <Grid x:Name="LayoutRoot" Background="White">

        <controls:WrapPanel x:Name="xRepeaterPanel"/>

    </Grid>

</UserControl>

UserControl: ImageRepeater.xaml.cs

public partial class ImageRepeater : UserControl

{

    public ImageRepeater()

    {

        InitializeComponent();

    }

 

    // The brush to paint on the rectangle

    private ImageBrush _BrushToTile = new ImageBrush();

    public ImageSource ImageSource

    {

        get { return _BrushToTile.ImageSource; }

        set {

            _BrushToTile.ImageSource = value;

        }

    }

 

    private double _ImageWidth;

    public double ImageWidth

    {

        get { return _ImageWidth; }

        set { _ImageWidth = value; }

    }

 

 

    private double _ImageHeight;

 

    public double ImageHeight

    {

        get { return _ImageHeight; }

        set { _ImageHeight = value; }

    }

 

    protected override Size ArrangeOverride(Size finalSize)

    {

        // To make sure that we fill the screen horizontally and vertically, we create negative margins

        Margin = new Thickness(0, 0, -ImageHeight, -ImageWidth);

 

        // Determine how many rectangles we need to add to fill the available screen width

        var itemCount = (int)Math.Ceiling(finalSize.Width / ImageWidth);

        itemCount = itemCount * (int)Math.Ceiling(finalSize.Height / ImageHeight);

 

        // It is done incrementally, so when the control is resized, we add more to it so fill the area again.

        var diff = itemCount - xRepeaterPanel.Children.Count();

        for (int i = 0; i < diff; i++)

        {

            // Create and add every rectangle

            var rect = new Rectangle();

            rect.Width = ImageWidth;

            rect.Height = ImageHeight;

            rect.Fill = _BrushToTile;

            xRepeaterPanel.Children.Add(rect);

        }

        return base.ArrangeOverride(finalSize);

    }

}

Stay in the light!

Robertjan Tuit



Goodbye Europe, Hello North America!

2 11 2008

I know I have been quiet lately, one of the effect of my move to Vancouver BC, Canada.

IMG_1171As some of you may know, I was asked to come and work for Microsoft, first in Vancouver B.C. Canada, and later to Redmond WA, USA.

So here I finally am, Downtown Vancouver, on the 16th floor  of this great apartment, finally having the time to get my blog up and running again. Everything went very smooth until now, so I guess all the preparations were worth it.

Just to get something straight, getting the Borg chip implemented will absolutely not stop me from blogging and I hope to blog more than I ever did. About my experiences here and of course to get as many Silverlight 2 info out there as possible.

For the Dutch people reading this, you can view one of my projects on American Election night. A Video player showing and playing Nbc, Fox, Ned 1 and Radio1. Visit http://amerikakiest.nos.nl on election night. Only viewable from inside the Netherlands.

Stay in the Light!

Robertjan Tuit



Software Development Conference 2008

20 09 2008

The 6th and 7th of October, we are organizing our 17th! SDN Conference. 2 days of international and national speakers. Be sure to be there for I believe that this year is going to be one of the best ones we ever did!

So if you haven’t gotten a ticket yet get it here

See you there!

.



Storyboard Animation for the ScrollViewer: AnimationHelperControl

13 09 2008

The Scrollviewer is a great panel and very easy to use. But it has a drawback. It uses a method to set the scrollbars and content position. This means you cannot use a storyboard animation to animate this.

I had 2 projects that required this functionality, and really needed a better solutions then using a DispatcherTimer to create the animation manually. And after a few good nights of sleep (I always have the best ideas after a good nights rest) I came up with what I think is a nice solution.

The idea is that you need a DependencyProperty to animate a Scrollviewer. But since the ScrollViewer is a Sealed control you can’t inherit from it, I needed to wrap a new control around it to make it reusable.

So I took a different approach, I created a AnimationHelperControl, which does not have any visuals but only has a Dependency property and an event that is fired when this property has been changed. In this way you can use it to control anything you want.

Below the source code for the control:

public class AnimationHelperControl : Control

{

    public AnimationHelperControl()

    {

        Visibility = Visibility.Collapsed;

    }

 

    public double DoubleValue

 

    {

        get { return (double)GetValue(DoubleValueProperty); }

        set

        {

            SetValue(DoubleValueProperty, value);

            DoubleValueChanged(value);

        }

    }

 

    public static readonly DependencyProperty DoubleValueProperty =

        DependencyProperty.Register("DoubleValue", typeof(double), typeof(AnimationHelperControl), new PropertyMetadata((sender, e) =>

            {

                if (e.OldValue != e.NewValue)

                {

                    var ah = (AnimationHelperControl)sender;

                    ah.DoubleValue = (double)e.NewValue;

                }

            }));

 

    public event EventHandler<DoubleEventArgs> DoubleValueChange;

    private void DoubleValueChanged(double newValue)

    {

        if (DoubleValueChange != null)

            DoubleValueChange(this, new DoubleEventArgs() { Value = newValue });

    }

}

 

public class DoubleEventArgs : EventArgs

{

 

    private double _Value;

    public double Value

    {

        get { return _Value; }

        set { _Value = value; }

    }

 

}

 

Then you add the control, the scrollviewer and 2 buttons to the page.xaml:

<Grid x:Name="LayoutRoot" Background="White">

    <Grid.RowDefinitions>

        <RowDefinition Height="0.853*"/>

        <RowDefinition Height="0.147*"/>

    </Grid.RowDefinitions>

    <local:AnimationHelperControl x:Name="xScrollViewerHorizontalOffset" Grid.RowSpan="2"/>

    <Grid Grid.RowSpan="1" Margin="0,0,0,0">

        <ScrollViewer x:Name="xScrollViewer" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">

            <ScrollViewer.Content>

                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">

                    <Rectangle Fill="Red" Width="300" Height="200" Margin="20,0,20,0"/>

                    <Rectangle Fill="Blue" Width="300" Height="200" Margin="0,0,20,0"/>

                    <Rectangle Fill="Green" Width="300" Height="200" Margin="0,0,20,0"/>

                    <Rectangle Fill="Purple" Width="300" Height="200" Margin="0,0,20,0"/>

                    <Rectangle Fill="Black" Width="300" Height="200" Margin="0,0,20,0"/>

                    <Rectangle Fill="Yellow" Width="300" Height="200" Margin="0,0,20,0"/>

                    <Rectangle Fill="Cyan" Width="300" Height="200" Margin="0,0,20,0"/>

                </StackPanel>

            </ScrollViewer.Content>

        </ScrollViewer>

    </Grid>

    <Button HorizontalAlignment="Left" Margin="8,8,0,8" VerticalAlignment="Stretch" Width="65" Content="Left" Grid.Row="1" x:Name="xButtonLeft"/>

    <Button HorizontalAlignment="Right" Margin="0,8,8,8" VerticalAlignment="Stretch" Width="66" Content="Right" Grid.Row="1" x:Name="xButtonRight"/>

</Grid>

 

Remember to the "local" namespace to the xaml.

Then we add the event handler to the page.xaml.cs:

xScrollViewerHorizontalOffset.DoubleValueChange += (sender, e) =>

{

    this.xScrollViewer.ScrollToHorizontalOffset(e.Value);

};

Now you could create storyboard animation on the DoubleValue property of the xScrollViewerHorizontalOffset control, but to keep it short and simple I’ll use the AnimateTo extension method of one of my previous posts, which accomplishes the same, only it does it with code. Let’s use the 2 buttons to animate scrolling left and right.

xButtonRight.Click += (sender, e) =>

{

    xScrollViewerHorizontalOffset.AnimateDoubleTo(200, "(StoryboardAnimationHelper.DoubleValue)", xScrollViewer.HorizontalOffset + 320);

};

xButtonLeft.Click += (sender, e) =>

{

    xScrollViewerHorizontalOffset.AnimateDoubleTo(200, "(StoryboardAnimationHelper.DoubleValue)", xScrollViewer.HorizontalOffset - 320);

};

 

That should do the trick I’ll try to upload a Demo Project later this weekend.

Stay in the light!

Robertjan Tuit