Getting browser screen & window information in a Silverlight 2 app

While working on visual verification and user interface testing support for some Silverlight tests, I came up with this simple file that abstracts out the Firefox/Safari and Internet Explorer property differences.  The browsers all expose this information in one way or another.

Although mostly integer values, numbers are returned as doubles to stay in line with how the HTML DOM bridge APIs work.

The properties exposed off of the static class are:

BrowserScreenInformation
ClientWidth, ClientHeight Current window’s inner size
ScrollLeft, ScrollTop Window’s scrolled portion relative to the page
ScreenWidth, ScreenHeight Screen resolution
AvailableScreenWidth, AvailableScreenHeight Real estate of the screen excluding the task bar or dock
ScreenPositionLeft, ScreenPositionTop Location, in pixels, of the window’s origin on the screen

Maybe someone will find this useful for their project!

using System;
using System.Windows;
using System.Windows.Browser;

namespace YourNamespaceHere
{
    /// <summary>
    /// Provides screen information about the browser
    /// </summary>
    /// <remarks>A simple proxy to JavaScript window and screen variables,
    /// abstracts away common web browser differences</remarks>
    public static class BrowserScreenInformation
    {

        /// <summary>
        /// During static instantiation, only the Netscape flag is checked
        /// </summary>
        static BrowserScreenInformation()
        {
            _isNavigator = HtmlPage.BrowserInformation.Name.Contains("Netscape");
        }

        /// <summary>
        /// Flag indicating Navigator/Firefox/Safari or Internet Explorer
        /// </summary>
        private static bool _isNavigator;

        /// <summary>
        /// Provides quick access to the window.screen ScriptObject
        /// </summary>
        private static ScriptObject Screen
        {
            get
            {
                ScriptObject screen = (ScriptObject)HtmlPage.Window.GetProperty("screen");

                if (screen == null)
                {
                    throw new InvalidOperationException();
                }

                return screen;
            }
        }

        /// <summary>
        /// Gets the window object's client width
        /// </summary>
        public static double ClientWidth
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("innerWidth")
                    : (double)HtmlPage.Document.Body.GetProperty("clientWidth");
            }

        }

        /// <summary>
        /// Gets the window object's client height
        /// </summary>
        public static double ClientHeight
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("innerHeight")
                    : (double)HtmlPage.Document.Body.GetProperty("clientHeight");
            }
        }

        /// <summary>
        /// Gets the current horizontal scrolling offset
        /// </summary>
        public static double ScrollLeft
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("pageXOffset")
                    : (double)HtmlPage.Document.Body.GetProperty("scrollLeft");
            }
        }

        /// <summary>
        /// Gets the current vertical scrolling offset
        /// </summary>
        public static double ScrollTop
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("pageYOffset")
                    : (double)HtmlPage.Document.Body.GetProperty("scrollHeight");
            }
        }

        /// <summary>
        /// Gets the width of the entire display
        /// </summary>
        public static double ScreenWidth
        {
            get
            {
                return (double)Screen.GetProperty("width");
            }
        }

        /// <summary>
        /// Gets the height of the entire display
        /// </summary>
        public static double ScreenHeight
        {
            get
            {
                return (double)Screen.GetProperty("height");
            }
        }

        /// <summary>
        /// Gets the width of the available screen real estate, excluding the dock
        /// or task bar
        /// </summary>
        public static double AvailableScreenWidth
        {
            get
            {
                return (double)Screen.GetProperty("availWidth");
            }
        }

        /// <summary>
        /// Gets the height of the available screen real estate, excluding the dock
        /// or task bar
        /// </summary>
        public static double AvailableScreenHeight
        {
            get
            {
                return (double)Screen.GetProperty("availHeight");
            }
        }

        /// <summary>
        /// Gets the absolute left pixel position of the window in display coordinates
        /// </summary>
        public static double ScreenPositionLeft
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("screenX")
                    : (double)HtmlPage.Window.GetProperty("screenLeft");
            }
        }

        /// <summary>
        /// Gets the absolute top pixel position of the window in display coordinates
        /// </summary>
        public static double ScreenPositionTop
        {
            get
            {
                return _isNavigator ? (double)HtmlPage.Window.GetProperty("screenY")
                    : (double)HtmlPage.Window.GetProperty("screenTop");
            }
        }

    }
}

Silverlight unit test framework download for Silverlight 2 Beta 2

If you’re looking for the latest Silverlight unit test framework download, look no further: I’ve packaged up the binaries and am making them available as a .Zip file download attached to this blog post.

These are the same exact binaries that we shipped at the MIX conference for Beta 1 - there’s very little that changed for unit testing since Beta 1.  Just a few days ago I posted the workaround steps and also updated Visual Studio 2008 test templates for Silverlight 2 Beta 2.

I had a great time meeting with customers at a recent "Ask the Experts" event in Redmond, thanks to everyone that attended, I received some great feedback on what people are looking forward to in the Silverlight testing space and will see what I can make happen!

Download the test framework

Download Microsoft.Silverlight.Testing.zip (160kb)
Installation instructions included in the Zip

Download the optional templates for Visual Studio

Details here

Unit test framework tutorial

My original walkthrough post will get you up and running in no time.  Also, ScottGu’s original post about the test framework.

Hope this helps.

Unit testing templates for Microsoft Silverlight 2 Beta 2

The unit test framework binaries that we released for Silverlight 2 Beta 1 work just fine with Silverlight 2 Beta 2, that was just released today.  However with the updated project file format for Beta 2, I’ve gone ahead and prepared updated templates that you should download and install.  There’s no need at this time to upgrade the actual test framework binaries.

Introducing Visual Basic test project templates for Beta 2

This was a big ask previously.  Today I’m providing both C# and VB project templates.

Download updated Visual Studio test project templates for Beta 2

To simplify adding test projects and classes to your .NET Silverlight applications and class libraries, these templates will quickly add a new test project and wire up the test framework so that you can right-click, set the StartUp project, and run the tests.

Unit test project template for Silverlight 2 Beta 2

C#: Download
VB: Download

To install: save this file into your “%userprofile%\Documents\Visual Studio 2008\Templates\ProjectTemplates” directory

Test class item template for Silverlight 2 Beta 2

C#: Download
VB: Download

To install: save this into “%userprofile%\Documents\Visual Studio 2008\Templates\ItemTemplates”

Upgrading your existing Silverlight 2 unit test projects

With the change to the Application::RootVisual property in Beta 2, the CreateTestPage return value needs to be cast to UIElement for updated test projects to compile.

Here’s how to update your existing C# test projects:

  1. Open your existing Silverlight unit test project application project in Visual Studio after installing Beta 2
  2. Perform an upgrade when prompted by Visual Studio
  3. Open the App.xaml.cs file
  4. Navigate to the Application_Startup method
  5. Modify the RootVisual line by inserting “(UIElement) ” before the call to UnitTestSystem.CreateTestPage.

Here’s what the updated Application_Startup line should look like:

private void Application_Startup(object sender, StartupEventArgs e)
{
    // Hook up and execute this test project
    this.RootVisual = (UIElement)UnitTestSystem.CreateTestPage(this);
}

What’s next

Now that Beta 2’s out there, on the test front you can expect in the coming weeks:

  • Updated drop of the Microsoft.Silverlight.Testing binaries with a small set of bug fixes and updated features
  • Simple continuous integration support (Team Foundation Build and CruiseControl.NET)
  • Test run reporting and perhaps some other surprises

Hope this helps!

Tech-Ed 2008: Building a great Microsoft Silverlight application talk on 6/6/08, 4:30pm in Blue Theater 2

Tech-Ed 2008’s in full swing right now in Orlando, Florida.  I wanted to let anyone in attendance know about an excellent talk coming up on Friday.

This year’s developer’s conference is full of exciting news, products, and talks.  With Silverlight 2 Beta 2 coming out soon, including a Go Live license, I’d highly recommend that you attend a talk on building great Silverlight apps.  They saved the best for last!

Tech-Ed 2008
"Tips, Tricks, and Techniques for Building a Great Microsoft Silverlight Application"
Kathy Kam

 

Friday, June 6th, 2008
4:30PM-5:45PM, Blue Theater 2

Track(s): Web and User Experience
Level: 300 - Advanced
Session type: Interactive Theaters

Kathy Kam is a Program Manager on the UI Frameworks team.  She owns a set of Silverlight 2 controls, including TabControl, Calendar, etc.  Check out the talk!

Dennis Dietrich: Stressing the importance of internationalization

Preface: One thing I’ve been meaning to do on my blog is introduce a number of the team members that I’ve been working closely with, to help give some insight into life inside the Microsoft Developer Division.  This marks the first of hopefully many such introductions.

The software industry has shipped excellent products in English, for United States keyboards.  But with modern frameworks fully supporting globalization and localization, we really should be spending more time making sure that we properly develop our applications to support a worldwide audience.  Dennis is one of many folks working day and night to improve the development process, overall quality, and education of developers to improve the state of things.

Dennis Dietrich is a Software Development Engineer in Test (SDET) who is passionate about doing globalization and localization right.  And right the first time.  A German expat living in Bellevue, WA, Dennis has created a body of excellent blog content that is worth taking a look at:

Before working in the division on projects like Silverlight & code-name “Acropolis,” Dennis was a developer in localization in Dublin, Ireland, where he was a member of the team that shipped Office for Macintosh in Dutch for the first time.

I hope you find Dennis’ blog interesting, I’d highly recommend subscribing to it.  He’s been pushing hard on globalization and localization scenarios in our Silverlight 2 work.

Storing text in the clipboard using Silverlight 2

To provide users the ability to copy permalinks or store other useful information in the clipboard, there aren’t many options for web developers today.  There’s no APIs inside JavaScript to access the clipboard.  Here’s a solution that will at least enable this from your Silverlight 2 app for most of your users.

Internet Explorer-only Clipboard Access

IE provides limited clipboard support in script. Using the interoperability features in Silverlight this data can be accessed.  The user will be prompted to approve the clipboard access using this method.

Open IE Clipboard demo (133k)
Requires Silverlight 2 Beta 1

Here’s the static clipboard method I created to attempt to write to the clipboard.  If the user denies the request, or the clipboard API is not available, an alert informs the user.  A successful write to the clipboard does not result in any visual confirmation.

Clipboard.cs:

using System;
using System.Windows.Browser;

namespace ClipboardDemo
{
    public static class Clipboard
    {
        const string HostNoClipboard = "The clipboard isn't available in the current host.";
        const string ClipboardFailure = "The text couldn't be copied into the clipboard.";

        /// <summary>
        /// Write to the clipboard (Internet Explorer-only)
        /// </summary>
        public static void SetText(string text)
        {
            // document.window.clipboardData.setData(format, data);
            var clipboardData = (ScriptObject)HtmlPage.Window.GetProperty("clipboardData");
            if (clipboardData != null) {
                bool success = (bool)clipboardData.Invoke("setData", "text", text);
                if (!success) {
                    HtmlPage.Window.Alert(ClipboardFailure);
                }
            }
            else {
                HtmlPage.Window.Alert(HostNoClipboard);
            }
        }

    }
}

In the button event handler in my demo app, I simply call the static method to write to the clipboard:

        private void Go_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(ClipboardText.Text);
        }

Cross-browser, cross-platform solution

Now, this one’s a little interesting: since Flash does have clipboard access, you can actually use it from the web browser (JavaScript) or even Silverlight 2 (HTML DOM bridge) to enable a cross-browser, cross-platform clipboard copy function.  It’s a hack, but does get the job done.

I think there’s enough space in the world’s hard drives for both Flash and Silverlight on every computer!

Open Cross-browser, Cross-platform Clipboard demo (133k)

Requires Silverlight 2 Beta 1

To do this, I’ll be using the Flash component that ships with the syntaxhighlighter tool created by Alex Gorbatchev.  By simply adding a new Flash embed to the page and referencing his clipboard.swf Flash movie file, the Flash API will then attempt to write the proper data into the clipboard.

The implementation I’ve done here isn’t super robust: if the user doesn’t have Flash, there’s no error message for instance.  If the user’s browser is Internet Explorer, or implements the clipboardData API, then the Flash workaround will not be used.

Here’s the expanded Clipboard.cs.  Do note, I’m hard-coding the clipboard.swf location, so make sure you’re using a valid path on your server.

Clipboard.swf:

Make sure to download this file (here syntaxhighlighter) and store it in the same directory as your application.

Clipboard.cs:

using System;
using System.Windows.Browser;

namespace ClipboardDemo
{
    public static class Clipboard
    {
        const string HostNoClipboard = "The clipboard isn't available in the current host.";
        const string ClipboardFailure = "The text couldn't be copied into the clipboard.";
        const string BeforeFlashCopy = "The text will now attempt to be copied...";
        const string FlashMimeType = "application/x-shockwave-flash";

        // HARD-CODED!
        const string ClipboardFlashMovie = "clipboard.swf";

        /// <summary>
        /// Write to the clipboard (IE and/or Flash)
        /// </summary>
        public static void SetText(string text)
        {
            // document.window.clipboardData.setData(format, data);
            var clipboardData = (ScriptObject)HtmlPage.Window.GetProperty("clipboardData");
            if (clipboardData != null) {
                bool success = (bool)clipboardData.Invoke("setData", "text", text);
                if (!success) {
                    HtmlPage.Window.Alert(ClipboardFailure);
                }
            }
            else {
                HtmlPage.Window.Alert(BeforeFlashCopy);

                // Append a Flash embed element with the data encoded
                string safeText = HttpUtility.UrlEncode(text);
                var elem = HtmlPage.Document.CreateElement("div");
                HtmlPage.Document.Body.AppendChild(elem);
                elem.SetProperty("innerHTML", "<embed src=\"" +
                    ClipboardFlashMovie + "\" " +
                    "FlashVars=\"clipboard=" + safeText + "\" width=\"0\" " +
                    "height=\"0\" type=\"" + FlashMimeType + "\"></embed>");
            }
        }

    }
}

Hope this helps!

Code display: Moving back from screen captures to text

Blog authors have always struggled (well, at least I have!) with the issue of pasting in code samples. In the past I’ve tried a few things, from using Visual Studio to WordPress formatting tools to Windows Live Writer plugins for code.  I settled on using screen captures, with the intention of attaching the code projects as downloadable text files.

Today, I’m making an attempt to move back to raw <pre /> tags, populated with text, that should be formatted on the fly by modern web browsers.  This is great for folks that visit my blog, but does deliver a less-than-attractive experience for newsreaders.

This is accomplished using:

Scott Guthrie’s monster blog posts are amazing, and the look is consistent everywhere.  This is because they’re full of Visual Studio + code screen captures.  I’m sure the syntax highlighter screen caps set off the latest wave of .NET developer’s color customizing that’s on all the dev’s machines that I’ve seen.

Here’s what C# code used to look like on my blog:

On to samples of the new system:

C#

    [TemplatePart(Name = HyperlinkButton.StateDisabledName, Type = typeof(Storyboard))]
    public partial class HyperlinkButton : ButtonBase
    {
        #region NavigateUri
        /// <summary>
        /// Gets or sets a URI to navigate to when the link is clicked.
        /// </summary>
        [TypeConverter(typeof(UriTypeConverter))]
        public Uri NavigateUri
        {
            get { return GetValue(NavigateUriProperty) as Uri; }
            set { SetValue(NavigateUriProperty, value); }
        }

Visual Basic

Imports Microsoft.Silverlight.Testing
Imports Microsoft.VisualStudio.TestTools.UnitTesting

<TestClass()> _
Public Class Class1

    ' This is a super simple test
    Public Sub SimpleTest()
        Assert.IsTrue(True)
    End Sub

End Class

JavaScript

var cssNode = document.createElement('link');
cssNode.type = 'text/css';
cssNode.rel = 'stylesheet';
cssNode.href = ss;
cssNode.media = 'screen';

// Append the new node
head.appendChild(cssNode);

XML

<?xml version="1.0" encoding="utf-8"?>
<items>
  <item type="photoset" id="395" owner="12037949754@N01"
		primary="6521" secret="5a3cc65d72" server="2"
		commentsold="1" commentsnew="1"
		views="33" photos="7" more="0">
    <title>A set of photos</title>
    <activity>
      <event type="comment"
			user="12037949754@N01" username="Bees"
			dateadded="1144086424">yay</event>
    </activity>
  </item>
</items>

XAML

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- Default style for System.Windows.Controls.Button -->
    <Style TargetType="Button">
        <Setter Property="IsEnabled" Value="true" />
        <Setter Property="IsTabStop" Value="true" />
        <Setter Property="Background" Value="#FF003255" />
        <Setter Property="Foreground" Value="#FF313131" />
        <Setter Property="MinWidth" Value="5" />
        <Setter Property="MinHeight" Value="5" />
        <Setter Property="Margin" Value="0" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Cursor" Value="Arrow" />

I’ll probably do some customizing of the highlighting brushes in the future, or see about porting the library to C# + Silverlight 2.  Let me know what you think about this change as I begin posting some new content: a step in the right direction?

Book Review: Pro C# 2008 and the .NET 3.5 Platform

Wow. This book rocks: Pro C# 2008 and the .NET 3.5 Platform, by Andrew Troelsen.  I’d recommend it to anyone that wants to get a lot of meat on 3.5 and down to business.  It’s a massive book and well worth making room for in your office collection.  It’s hard cover.

When I picked up the book several months ago, my main intention was to get everything I needed to grok 3.5, after being focused on Silverlight for a while I realized that I wasn’t making full use of LINQ and other sexy features in my code.  This reference did it for me, with MSDN as my backup for any of the nitty gritty topics like lambdas and expression trees.  Today I’m still using the book often as a clear way to introduce others to the new platform.

A nice bonus was the ability to grab a PDF of the entire book from Apress for free after buying the book.  I don’t know if this is a sign of the future or not, but being able to pull the book up in Adobe Acrobat has been almost as useful as being able to take the book to my favorite coffee shop to focus on the new 3.5 platform.

Don’t expect this book to tell you how to create a data structure, or what a ‘for’ loop is.  The title is prefixed by Pro and it isn’t joking.  This was enjoyable compared to many of today’s books that fill a few hundred pages with the obvious.

What surprised me, and many .NET developers will appreciate beyond the awesome C# 3.5 coverage: Details on so much of all things .NET – this is NOT a book for niche developers (web- only, client- only, looking to figure out XAML), but rather for enthusiasts, experts and technologists looking for breadth of knowledge.  There’s some coverage of WPF.  In-depth CLR stuff: assemblies, metadata, IL.

At the end of the day, C# 3.5 is great.  Where I thought that generics were the bomb in 2.0, it is now obvious that C# has grown quite a bit since then.

Book organization

The Table of Contents can be downloaded online.  The book is organized into these sections:

  • Introducing C# and the .NET Platform
  • Core C# Programming Constructs
  • Advanced C# Programming Constructs
  • Programming with .NET Assemblies
  • Introducing the .NET Base Class Libraries
  • Desktop User Interfaces
  • Building Web Applications with ASP.NET
  • Appendixes

You’ll also find the book’s summary, source, bonus chapters, and a sample chapter on the Philosophy of .NET (kind of like a quick boot camp for pros) on the Apress.com site for the book.

Note, there’s also now a VB edition of this book available.  I’m not familiar with it, but since it’s also by Andrew Troelsen, I’ll assume that a lot of the material overlaps, especially on the full stack and platform coverage.  Might be a good candidate to browse at a local bookseller.

Hope you find the book as helpful!

Next Page »