Evolution of Windows Explorer

Nice post of Steven Sinofsky on MSDN blogs about the history and future of Windows Explorer.
http://blogs.msdn.com/b/b8/archive/2011/08/29/improvements-in-windows-explorer.aspx

(edit 31-08-2011)
And Martin Tirion of Microsoft Netherlands wrote about it a day later (in Dutch).
http://blogs.microsoft.nl/blogs/ux/archive/2011/08/30/windows-explorer-in-windows-8-en-user-experience.aspx

Datadrop Website Load Tool

In the last months I’ve experienced a lot of problems with my current internet connection. Due to mysterious reasons there have been data-drops at random times for random periods.

I’ve contacted my ISP (Online.nl), and told them my story. But every time they’ve called me back, they said that they could not find the problem. My connection was always fine.

Irritated by the fact that they could not solve my problem, I asked them what they would need to fix the problem. They answered that they need proof of the failing connection.

So I’ve created a solution.

At the moment they probably are only testing with pings, and my problem isn’t actually a failing connection, but data-loss due package-drops.
So I’ve searched for an small application that I can run on my HomeServer, which measures the internet connection.
Unfortunately I have only found Ping-testers, which wasn’t exactly where I was looking for.

Therefore I’ve decided to build my own tester.

Website Load Toolscreenshot

The website load tool is a small application build on WPF .Net 4 that will download data with a configurable interval from defined URI’s.
So you set up a series of websites with an test interval of 60 seconds, and keep it running for several days.
Changes of state are written in a Log, so you can collect you own evidence of the stability of your connection.

I’ve released the application on CodePlex, so everybody is free to use it.
It also can come in handy if you need to check network-stability or the availability of your website.

Get it at websiteloadtool.codeplex.com.

Storing and retrieving WPF RibbonWindow settings (including the usercustomizable QuickAccessToolbar)

When you’re creating a desktop application you’d probably want to store some user settings.
Especially when using the Ribbon inside your application, there are several things (like RibbonIsMinimized and ShowQuickAccessToolBarOnTop) that users can set and want to keep even if the application en closed and restarted.

There are several ways to store these user settings, and you can find some methods if you search the internet. But the biggest challenge is to store and retrieve the Quick Access Toolbar content which the user can change.

Defining

First the storage of the settings. I use the application user properties which are set through the project settings.
We define the following settings:

  • FirstRun (bool)
  • WindowSize (System.Windows.Size)
  • WindowLocation (System.Windows.Point)
  • WindowState (System.Windows.WindowState)
  • RibbonIsMinimized (bool)
  • ShowQuickAccessToolbarOnTop (bool)
  • RibbonQuickAccessToolbar (string)

ProjectSettings

If you can’t find the right type inside the type combobox, just select [Browse…] to select it from available DLL’s. Point and Size are found in WindowsBase, and WindowState is in PresentationFramework.

Storing

Next step is storing the settings. I leave the QuickAccessToolbar out for this moment. I’ll add it later.

The storing is taking place in de code behind of the Shell, which is the main window of the current application. It is not mandatory to do this in the code behind, but for the moment it is the easiest.

I store the settings when the window is closing.

protected override void OnClosing(CancelEventArgs e)
{
    Properties.Settings.Default.FirstRun = false;
    Properties.Settings.Default.WindowSize = new Size(Width, Height);
    Properties.Settings.Default.WindowLocation = new Point(Left, Top);
    Properties.Settings.Default.WindowState = WindowState;
    Properties.Settings.Default.RibbonIsMinimized = RibbonMenu.IsMinimized;
    Properties.Settings.Default.ShowQuickAccessToolBarOnTop = RibbonMenu.ShowQuickAccessToolBarOnTop;
    Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);

    Properties.Settings.Default.Save();

    base.OnClosing(e);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The RibbonMenu is referencing to the <Ribbon x:Name="RibbonMenu" > inside the Shell.XAML.

Width, Height, Left, Top and WindowState are properties of the WPF (Ribbon)Window.

Retrieving

And when the application is starting again, you just have to get these settings and set them back. The best moment to do this is in the OnInitialized of the Shell.

protected override void OnInitialized(EventArgs e)
{
    base.OnInitialized(e);

    if (!Properties.Settings.Default.FirstRun)
    {
        Width = Properties.Settings.Default.WindowSize.Width;
        Height = Properties.Settings.Default.WindowSize.Height;
        Left = Properties.Settings.Default.WindowLocation.X;
        Top = Properties.Settings.Default.WindowLocation.Y;
        WindowState = Properties.Settings.Default.WindowState;
        RibbonMenu.IsMinimized = Properties.Settings.Default.RibbonIsMinimized;
        RibbonMenu.ShowQuickAccessToolBarOnTop = Properties.Settings.Default.ShowQuickAccessToolBarOnTop;
    }
}

So far the easy part.

QuickAccessToolbar

Storing and retrieving the QuickAccessToolbar is a bit more complicated. Because this can’t just be serialized. 
First I tried and used XamlWriter and XamlReader to try serialize the items inside the QuickAccessToolbar. Although storing it worked fine (it made a huge xml file), when trying to load the Xaml, I soon experienced the problem that the XamlWriter also serialized the bindings (with it’s content) i set on the command property. Unfortunately these bindings are DelegateCommands from Prism, which can’t be constructed through deserialization.

The solution is a bit complex, but it works just fine. I created my own entities for storing and retrieving the items inside the QuickAccessToolbar.

[Serializable]
public class QuickAccessToolbarButtonCollection : List<QuickAccessToolbarButton> { }

[Serializable]
public class QuickAccessToolbarButton
{
    public ImageSource LargeImageSource { get; set; }
    public ImageSource SmallImageSource { get; set; }
    public string Label { get; set; }
    public object QuickAccessToolBarId { get; set; }
    public object ToolTip { get; set; }
    public string ToolTipDescription { get; set; }
    public string KeyTip { get; set; }
    public Binding CommandBinding { get; set; }
}

Off course you can add more properties if you’re setting more attributes on the RibbonButton. These properties were everything I’ve used.

Next step is creating and storing the QuickAccessToolbar items.

#region Create the QuickAccessToolbarButtonCollection
QuickAccessToolbarButtonCollection buttons = new QuickAccessToolbarButtonCollection();

foreach (RibbonButton rButton in RibbonMenu.QuickAccessToolBar.Items)
{
    if (rButton.KeyTip != "S") // Don't include the savebutton!
    {
        QuickAccessToolbarButton qaButton = new QuickAccessToolbarButton()
        {
            Label = rButton.Label,
            KeyTip = rButton.KeyTip,
            LargeImageSource = rButton.LargeImageSource,
            SmallImageSource = rButton.SmallImageSource,
            ToolTip = rButton.ToolTip,
            ToolTipDescription = rButton.ToolTipDescription,
            QuickAccessToolBarId = rButton.QuickAccessToolBarId,
            CommandBinding = BindingOperations.GetBinding(rButton, RibbonButton.CommandProperty)
        };
        buttons.Add(qaButton);
    }
}
#endregion

And when the collection filled, I use the XamlWriter to set this data inside a user setting

Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);

The reason I’m not using a conventional XMLSerializer is because the XamlWriter can serialize bindings.

Last step is to read the stored setting. For this I use the XamlReader to deserialize back to our custom entity.

#region Load the QuickAccessToolbarButtonCollection
if (!string.IsNullOrEmpty(Properties.Settings.Default.RibbonQuickAccessToolBar))
{
    QuickAccessToolbarButtonCollection buttons = null;
    using (StringReader stringReader = new StringReader(Properties.Settings.Default.RibbonQuickAccessToolBar))
    {
        XmlReader xmlReader = XmlReader.Create(stringReader);
        buttons = (QuickAccessToolbarButtonCollection)XamlReader.Load(xmlReader);
        xmlReader.Close();
    }

    if (buttons != null)
    {
        for (int i = RibbonMenu.QuickAccessToolBar.Items.Count - 1; i >= 0; i--)
        {
            RibbonButton button = (RibbonButton)RibbonMenu.QuickAccessToolBar.Items.GetItemAt(i);
            if (button.KeyTip != "S") // Don't delete the savebutton!
                RibbonMenu.QuickAccessToolBar.Items.RemoveAt(i);
        }

        foreach (QuickAccessToolbarButton qaButton in buttons)
        {
            RibbonButton rButton = new RibbonButton()
            {
                Label = qaButton.Label,
                KeyTip = qaButton.KeyTip,
                LargeImageSource = qaButton.LargeImageSource,
                SmallImageSource = qaButton.SmallImageSource,
                ToolTip = qaButton.ToolTip,
                ToolTipDescription = qaButton.ToolTipDescription,
                QuickAccessToolBarId = qaButton.QuickAccessToolBarId
            };
            if (qaButton.CommandBinding != null)
                SetBinding(RibbonButton.CommandProperty, qaButton.CommandBinding);

            RibbonMenu.QuickAccessToolBar.Items.Add(rButton);
        }
    }
}
#endregion

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Check explicitly if the commandbinding are null, else you get exceptions when initializing the Shell.

 

Overview

Below the complete two methods.

protected override void OnInitialized(EventArgs e)
{
    base.OnInitialized(e);

    if (!Properties.Settings.Default.FirstRun)
    {
        Width = Properties.Settings.Default.WindowSize.Width;
        Height = Properties.Settings.Default.WindowSize.Height;
        Left = Properties.Settings.Default.WindowLocation.X;
        Top = Properties.Settings.Default.WindowLocation.Y;
        WindowState = Properties.Settings.Default.WindowState;
        RibbonMenu.IsMinimized = Properties.Settings.Default.RibbonIsMinimized;
        RibbonMenu.ShowQuickAccessToolBarOnTop = Properties.Settings.Default.ShowQuickAccessToolBarOnTop;

        #region Load the QuickAccessToolbarButtonCollection
        if (!string.IsNullOrEmpty(Properties.Settings.Default.RibbonQuickAccessToolBar))
        {
            QuickAccessToolbarButtonCollection buttons = null;
            using (StringReader stringReader = new StringReader(Properties.Settings.Default.RibbonQuickAccessToolBar))
            {
                XmlReader xmlReader = XmlReader.Create(stringReader);
                buttons = (QuickAccessToolbarButtonCollection)XamlReader.Load(xmlReader);
                xmlReader.Close();
            }

            if (buttons != null)
            {
                for (int i = RibbonMenu.QuickAccessToolBar.Items.Count - 1; i >= 0; i--)
                {
                    RibbonButton button = (RibbonButton)RibbonMenu.QuickAccessToolBar.Items.GetItemAt(i);
                    if (button.KeyTip != "S") // Don't delete the savebutton!
                        RibbonMenu.QuickAccessToolBar.Items.RemoveAt(i);
                }

                foreach (QuickAccessToolbarButton qaButton in buttons)
                {
                    RibbonButton rButton = new RibbonButton()
                    {
                        Label = qaButton.Label,
                        KeyTip = qaButton.KeyTip,
                        LargeImageSource = qaButton.LargeImageSource,
                        SmallImageSource = qaButton.SmallImageSource,
                        ToolTip = qaButton.ToolTip,
                        ToolTipDescription = qaButton.ToolTipDescription,
                        QuickAccessToolBarId = qaButton.QuickAccessToolBarId
                    };
                    if (qaButton.CommandBinding != null)
                        SetBinding(RibbonButton.CommandProperty, qaButton.CommandBinding);

                    RibbonMenu.QuickAccessToolBar.Items.Add(rButton);
                }
            }
        }
        #endregion
    }
}

protected override void OnClosing(CancelEventArgs e)
{
    #region Create the QuickAccessToolbarButtonCollection
    QuickAccessToolbarButtonCollection buttons = new QuickAccessToolbarButtonCollection();

    foreach (RibbonButton rButton in RibbonMenu.QuickAccessToolBar.Items)
    {
        if (rButton.KeyTip != "S") // Don't include the savebutton!
        {
            QuickAccessToolbarButton qaButton = new QuickAccessToolbarButton()
            {
                Label = rButton.Label,
                KeyTip = rButton.KeyTip,
                LargeImageSource = rButton.LargeImageSource,
                SmallImageSource = rButton.SmallImageSource,
                ToolTip = rButton.ToolTip,
                ToolTipDescription = rButton.ToolTipDescription,
                QuickAccessToolBarId = rButton.QuickAccessToolBarId,
                CommandBinding = BindingOperations.GetBinding(rButton, RibbonButton.CommandProperty)
            };
            buttons.Add(qaButton);
        }
    }
    #endregion

    Properties.Settings.Default.FirstRun = false;
    Properties.Settings.Default.WindowSize = new Size(Width, Height);
    Properties.Settings.Default.WindowLocation = new Point(Left, Top);
    Properties.Settings.Default.WindowState = WindowState;
    Properties.Settings.Default.RibbonIsMinimized = RibbonMenu.IsMinimized;
    Properties.Settings.Default.ShowQuickAccessToolBarOnTop = RibbonMenu.ShowQuickAccessToolBarOnTop;
    Properties.Settings.Default.RibbonQuickAccessToolBar = XamlWriter.Save(buttons);

    Properties.Settings.Default.Save();

    base.OnClosing(e);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Enjoy!

Microsoft Silverlight 5.0 features for developers

Recently on Silverlight 5.0 Firestarter event ScottGu has announced road map for Silverlight 5.0. There will be lots of features that will be there in Silverlight 5.0 but here are few glimpses of Silverlight 5.0 Features.

 

Improved Data binding support and Better support for MVVM:

One of the greatest strength of Silverlight is its data binding. Microsoft is going to enhanced data binding by providing more ability to debug it. Developer will able to debug the binding expression and other stuff in Silverlight 5.0. Its also going to provide Ancestor Relative source binding which will allow property to bind with container control. MVVM pattern support will also be enhanced.

 

Performance and Speed Enhancement:

Now Silverlight 5.0 will have support for 64bit browser support. So now you can use that Silverlight application on 64 bit platform also. There is no need to take extra care for it.It will also have faster startup time and greater support for hardware acceleration. It will also provide end to end support for hard acceleration features of IE 9.

 

More support for Out Of Browser Application:

With Silverlight 4.0 Microsoft has announced new features called out of browser application and it has amazed lots of developer because now possibilities are unlimited with it. Now in Silverlight 5.0 Out Of Browser application will have ability to Create Manage child windows just like windows forms or WPF Application. So you can fill power of desktop application with your out of browser application.

 

Testing Support with Visual Studio 2010:

Microsoft is going to add automated UI Testing support with Visual Studio 2010 with Silverlight 5.0. So now we can test UI of Silverlight much faster.

 

Better Support for RIA Services:

RIA Services allows us to create N-tier application with Silverlight via creating proxy classes on client and server both side. Now it will more features like complex type support, Custom type support for MVVM(Model View View Model) pattern.

 

WCF Enhancements:

There are lots of enhancement with WCF but key enhancement will WSTrust support.

 

Text and Printing Support:

Silverlight 5.0 will support vector base graphics. It will also support multicolumn text flow and linked text containers. It will full open type support,Postscript vector enhancement.

 

Improved Power Enhancement:

This will prevent screensaver from activating while you are watching videos on Silverlight. Silverlight 5.0 is going add that smartness so it can determine while you are going to watch video and while you are not going watch videos.

 

Better support for graphics:

Silverlight 5.0 will provide in-depth support for 3D API. Now 3D rendering support is more enhancement in Silverlight and 3D graphics can be rendered easily.

You can find more details on following links and also don’t forgot to view Silverlight Firestarter keynote video of ScottGu.

 

http://www.silverlight.net/news/events/firestarter-labs/

http://blogs.msdn.com/b/katriend/archive/2010/12/06/silverlight-5-features-firestarter-keynote-and-sessions-resources.aspx

http://weblogs.asp.net/scottgu/archive/2010/12/02/announcing-silverlight-5.aspx

http://www.silverlight.net/news/events/firestarter/

http://www.microsoft.com/silverlight/future/

 

From http://jalpesh.blogspot.com/2010/12/microsoft-silverlight-50-features-for.html

Silverlight Resize Drag Behavior for targeted UIElements

I have been searching for a Silverlight behavior where you have the ability to resize a column. Normally you can do such a thing with a GridSplitter onto a grid with several columns.

Unfortunately this doesn’t work when you also wants to implement something like a hide and show menu column.

Therefore I created this behavior myself and released it on CodePlex. So if you are developing a Silverlight application and you find yourself in need of a simple behavior that allows you to resize an element by dragging either in height or width, go to the ResizeDragBehavior on Codeplex.

The solution also includes a sample project where you can see how you can easily setup a menupanel-based interface.

ResizeDragBehavior

The behavior is fully compatible with Expression Blend.

The Ten Commandments of User Experience

  • 1st commandment

    The user is always right

    You are not the user. Neither is your boss

     

  • 2nd commandment

    Understand the User

     

  • 3th commandment

    Avoid Solutioneering

    Identify & fully understand problems before finding solutions

     

  • 4th commandment

    Form follows function

    Form must play within the general realm of the familiar for easily understood functions.

     

  • 5th commandment

    Content is king

    Design is about communication, and takes more than pixels to communicate.

    95% of web users do not read 80% of your content.
    This doesn’t mean that your content isn’t important, it means it’s more important.

     

  • 6th commandment

    Innovate, do not Imitate

     

  • 7th commandment

    Access is for Everyone

     

  • 8th commandment

    Plan before you Design

    With our users in mind and the right vision, we can plan, and develop successful applications.

     

  • 9th commandment

    Understand the Goal

    Executives can no longer afford to formulate strategy without embracing user experience.

    If your website could do only one small thing, what would that one thing be?

     

  • 10th commandment

    Learn from Failure

    Failure is success if we learn from it.

     

From Nick Finck and Raina Van Cleave’s presentation from SXSWi.

Home Server µTorrent IIS Web Access Client

At home I have a Windows Home Server which also has µTorrent running as a service. Luckily this application comes default with a Web Access which allows you to manage µTorrent without having a user logged in on your server. (installing µTorrent on your server as a service described here.)

What happens is that the Web Access is made available on another port. Something like http://homeserver:39295/gui/. And this might become a problem if you want to reach your Web Client from outside your personal network. Of course you can solve this by setting the port-forwarding, but in my case I wasn’t allowed to reach non-default ports when I was at work. The firewalls block these ports.

But because I am allowed to reach the default port 80 on my home server, I wondered if it was possible to have the Web Client on the IIS of the Home Server. Unfortunately is the µTorrent Web Access client not meant for this, so I looked around to see if there where other Web Access clients which does the same.

I did found one solution, and although it worked, it wasn’t exactly what I had in mind.

So i created a little personal project to create a really simple µTorrent Web Access client that runs on IIS, so I have access to it from work. And now I have something working, I might as well share it for those who want to use it (or extend it).

uTorrent

It is a very basic solution, with lots of improvement possible. But it works.

The communication with µTorrent is realized by the DLL in the µTorrent Web Client API Wrapper Library project on CodePlex. This worked like a charm, except it throws an exception when trying to delete a torrent. (Can’t figure out what it is, but the functionality still works, you just receive a message)

My solution is based on the ASP.NET Ajax Control Toolkit, so if you wish to develop on it, you need that installed. 

Download here the entire solution:

Download here the Web Access client:

Just another BloggingAbout.NET site