Sunday, May 11, 2008

Is Silverlight just another buzzword?

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/is_silverlight_just_another_buzzword.htm]

There are always new buzzwords coming out in software development. One of those buzzwords gaining more traction is "Silverlight", a Microsoft technology to enable rich UI web applications.

I think that Silverlight is great, and is far more than a buzzword. I see it offering several big benefits:

  1. Graphical API -  Silverlight lets you draw and animate vector graphics. For example, you could easily do a graph. ASP.Net had ways to handle this, but they were slow and cumbersome (for example, use GDI+ to create the image on your server, and then load it up).
  2. Programming a compiled language (like C#) on the client - This is just awesome. Whether you've written an entire physics engine that you're running on the client, or just doing complex validation, the ability to code difficult logic in a first class language like C#, as opposed to a brittle scripting language, is invaluable.
  3. Rich object and event model - no more postbacks, easy to add controls, etc... - You could modify the DOM using JS, but it's so much easier to do this with Silverlight. For example, try dynamically adding an entire complex UserControl with JavaScript - it's doable, but hard. It's one line in silverlight.
  4. Cross-browser compliant - Silverlight just works on the main browsers (IE, Firefox, etc...). No more pulling your hair out because you forgot to check some DOM method nuance.
  5. UI rendered through xaml - Silverlight lets you create your "Form" via a markup language, somewhat like Html, but much cleaner. I think this is a cleaner style than creating it via the codeBehind (like WinForms).

How does Silverlight doe this? In one sense, it "cheats" by requiring a small download (kind of like a flash player). So, Silverlight isn't just like Ajax, which plays by the rules of the web but just stretches them by leveraging the XmlHttpRequest object, but rather Silverlight plays a whole new game.

Monday, April 21, 2008

JavaScript enums

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/javascript_enums.htm]

While JavaScript does not explicitly have the enum keyword, you can work around it using JS rich objects to get the functional equivalent. Here's a minimalist example that defines the enum, passes it in as a parameter, and then checks for it in a switch-case statement. Although, this doesn't throw a "compile time" exception if you pass in an invalid value.

    var Enum_Colors =
    {
      Red:0,
      Blue:1,
      Green:2,
      Yellow:3
    };

   
    function DoStuff()
    {
      TestEnum(Enum_Colors.Green);
    }

    function DoError()
    {
      TestEnum(Enum_Colors.Unknown); //Bad
    }
    function TestEnum(objColorEnum)
    {
      var str;
      switch(objColorEnum)
      {
        case Enum_Colors.Red:
          str = "red";
          break;
        case Enum_Colors.Blue:
          str = "blue";
          break;
        case Enum_Colors.Green:
          str = "green";
          break;
        case Enum_Colors.Yellow:
          str = "yellow";
          break;
        default:
          str = "none";
          break;
      }
     
      alert("The enum passed in is: " + str);
    }

 Thanks to VS2008, you at least get JS intellisence on the "Enum_Colors" object, so that's better than just typing in error-prone literal strings.

Sunday, April 20, 2008

Convert from a MemoryStream to a string and back

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/convert_from_a_memorystream_to_a_string_and_back.htm]

A stream in .Net is a sequence of bytes. There are several types of streams. A common one is the MemoryStream which uses memory for its storage (as opposed to a file system, or something else). Several readers and writers require a stream as an input parameter, and you'll find that sometimes you'll just want to be able to easily convert from a string to a MemoryStream and back. Here are two easy utility methods to do that:

    public static string GetStringFromMemoryStream(MemoryStream m)
    {
      if (m == null || m.Length == 0)
        return null;

      m.Flush();
      m.Position = 0;
      StreamReader sr = new StreamReader(m);
      string s = sr.ReadToEnd();

      return s;
    }

    public static MemoryStream GetMemoryStreamFromString(string s)
    {
      if (s == null || s.Length == 0)
        return null;

      MemoryStream m = new MemoryStream();
      StreamWriter sw = new StreamWriter(m);
      sw.Write(s);
      sw.Flush();

      return m;
    }

 

We can easily test these with a round-trip method. Note that ideally we'd have one test for each specific method, but this is just for demo purposes:

 

    [TestMethod]
    public void Convert_RoundTrip()
    {
      string s1 = "Hello World!";
      MemoryStream m = GetMemoryStreamFromString(s1);

      Assert.AreEqual(12, m.Length);

      string s2 = GetStringFromMemoryStream(m);

      Assert.AreEqual(s1, s2);
    }

 

 

Thursday, April 10, 2008

My Startup Script

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/my_startup_script.htm]

 

I don't like re-starting my machine because I need to re-open all the misc windows and files I have loaded. However, because I still need to reboot, I wrote a simple script to open common programs and files for me.

REM: Open Windows Explorer

start explorer
start explorer

REM: Open NotePad

start notepad
start notepad "C:\MyDocuments\temp.txt"

REM: Open the DOS command window, default to a certain folder

start cmd "/Kcd C:\Utils\MyTasks"

REM: Open Internet Explorer

start /B /D"C:\Program Files\Internet Explorer" iexplore.exe

REM: Open a Visual Studio solution

start /B /D"C:\MySolutions\StandardFiles" StandardFiles.sln

This opens five main things:

  • Windows Explorer

  • Notepad - a blank version, and one that stores a simple scratchpad of notes. You could also open other scratchpads.

  • Internet Explorer (could just as easily be firefox). There are also ways to pre-populate the tabs.

  • Cmd window - I set it to a directory that has a bunch of misc scripts (using the "/K" switch to call the CD command)

  • Visual Studio - In this case I open a solution folder with a bunch of misc xml files that I use.

Of course you can add other programs to the list too.

 

Lastly, I made a shortcut of this batch script on my desktop, so I just click it when Windows loads up. (You could probably automate the startup tasks if you want).

Wednesday, April 9, 2008

Silverlight Xaml error: "Length cannot be less than zero. Parameter name: length"

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/silverlight_xaml_error_length_cannot_be_less_than_zero_pa.htm]

I was getting a strange Silverlight compile error in my Page.xaml the other day (while migrating stuff from 1.1 Alpha to 2.0 Beta):

Length cannot be less than zero.
Parameter name: length

At first it sounds like I was setting a wrong value - like trying to reference the "-1" position on a string. But, it actually was a constraint in what namespaces Xaml allows.

 

In 1.1 Alpha, this would be ok:

xmlns:Tank.Core="clr-namespace:Tank.Core;assembly=Tank.Core"

Which you could then reference like so:

However, that line kept throwing the error when I tried to compile.

 

It seems like if I remove the period ".", then it works again, like so:

xmlns:Tank1="clr-namespace:Tank.Core;assembly=Tank.Core"

Strange. I'm not fully sure why, maybe some parsing thing with periods "." in beta, but it was good to have a work-around.

Tuesday, April 8, 2008

Excuses for installing a game on your work laptop

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/excuses_for_installing_a_game_on_your_work_laptop.htm]

Of course work laptops are for work, and should only be used for "company purposes". So, how do some people justify installing games on their work machines:
  • "It's part of the operating system - Windows won't run unless I install these games. Really."

  • "By installing on my main work laptop, I'm using that laptop more, so I'm more familiar with how it works and I can more easily check work-related tasks (like email and IM, and things that require the VPN)."

  • "These games have technical educational value, and are therefore not really 'games', but rather learning tutorials that benefit the company."

  • "I'm not 'playing the game', I'm studying it to better understand how to make functional user interfaces."

  • "I'm just analyzing the deployment experience so I can glean from it and apply it to our own product."

  • "This isn't really a game, it's actually a test project that I wrote myself (such as with XNA or Silverlight)."

  • "This game was built by one of our clients, so I'm just studying their products to help me conduct better client outreach."

I'm sure there's more.

Thursday, March 27, 2008

Fast cloning of dropdowns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/fast_cloning_of_dropdowns.htm]

There are times that you'll want to dynamically add items to an html dropdown using JavaScript. It can be a huge performance gain, even with Ajax and update panels. You can easily do this like so:

 

      function DoStuff()
      {
        var selectbox = document.getElementById("Select1");
        addOption(selectbox, "AAA", "1");
        addOption(selectbox, "BBBBB", "2");
        addOption(selectbox, "CC", "3");
       
      }
   
      function addOption(selectbox, strText, strValue )
      {
        var optn2 = document.createElement("OPTION");
        optn2.text = strText;
        optn2.value = strValue;
        selectbox.options.add(optn2);    //This line is very slow
      }

 

The problem I wanted to solve was how to do this when adding 4000 items? It could take several seconds, and be very slow. (Yes, ideally a simple dropdown by definition doesn't have that many items, but let's say there are legacy constraints there, and the client wants a dropdown). For example, say you have a grid, each row has a dropdown, and that dropdown may be huge. A much faster way is to load only 1 dropdown, make it hidden (via JS on the client), and then clone it's nodes.

 

For example, have a hidden dropdown, which you populate from whatever server values:

 

<span id="Span1">span

And then, call this function to clone those values. It will clone the entire dropdown (sparing you from calling the very slow options.add method 4000 times), and then dump it in some nested container (like a span):

 

      function cloneDropdowns_fast(strSourceId, strContainerId)
      {
        o = document.getElementById(strSourceId).cloneNode(true);
        o.style.visibility = "";
        var container = document.getElementById(strContainerId);
        container.appendChild(o);
      }

 

      function PopulateDropdown()
      {
        cloneDropdowns_fast("Select2", "Span1");
      }

 

So, calling the method "PopulateDropdown" will copy the entire dropdown from "Select2", and dump a whole new dropdown in the "Span1" container. It works much faster (and appears to work in both IE and FF).