July 2007 - Posts

Visual Studio beta 2 is out
Fri, Jul 27 2007 10:48

Get it from here.

by luisabreu | with no comments
Filed under:
Silverlight: the XAML ASP.NET control and embeded XAML
Wed, Jul 25 2007 11:30

Even though the Xaml's XamlUrl porperty seems to indicate that it can only load XAML from an existing url, the truth is that you can also pass it a reference to a XAML excerpt which is embeded on the page. here's a quick example of how you can do this:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <script type="text/xaml" id="xamlContent">
      <Canvas
        x:Name="parentCanvas"
        xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="640"
        Height="480"
        Background="Wheat">
        <TextBlock
          Canvas.Left="20"
          FontSize="24"
          Text="Hi"/>
      </Canvas>
    </script>

    <form id="form1" runat="server">
    <asp:ScriptManager runat="server" ID="manager" />
    <div>
        <asp:Xaml runat="server"
            Height="400"
            Width="600"
            XamlUrl="#xamlContent"
            ID="myXaml" ></asp:Xaml>
    </div>
    </form>
</body>
</html>

by luisabreu | 2 comment(s)
Filed under:
Silverlight: building a simple progress bar
Wed, Jul 25 2007 10:51

When you're developing a Silverlight application, you'll surelly be in a situation where you need to download stuff before starting your app. In these cases, you should play nice with the user and give them some indications regarding what's going on. The most common thing to do in these scenarios is to show a progress bar.

Building a progress bar in silverlight is simple and I'll try to show you how you can build one quickly. In my example, I've built a simple UserControl that you can reuse to show the progress of a task. Here's what I've got in the XAML file:

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="300"
Height="22">
<Rectangle Stroke="#FF000000" StrokeThickness="1" x:Name="border"
Canvas.ZIndex="2"
Width="298" Height="22" Canvas.Left="0" Canvas.Top="0" />
<Rectangle Stroke="#FF000000" StrokeThickness="0" x:Name="fill"
Width="298" Height="22" Canvas.Left="0" Canvas.Top="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFDD9090" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock x:Name="info" Width="50" Height="19" Canvas.Left="125" Canvas.Top="3" FontSize="9" Text="100%" TextWrapping="Wrap"/>
</Canvas>

Now, the code:

namespace Silverlight.Controls
{
  public class ProgressBar : Control
  {
    private Canvas _root;

    public ProgressBar()
    {
          System.IO.Stream s = this.GetType().Assembly.GetManifestResourceStream("SilverlightProgressBar.ProgressBar.xaml");
         _root = (Canvas)this.InitializeFromXaml(new System.IO.StreamReader(s).ReadToEnd());

         UpdateInfoPos();
         UpdateUI(0);
   }

   public double CtlHeight
   {
       get { return _root.Height; }
       set
      {
       _root.Height = value;
       ProgressRect.Height = _root.Height = ProgressRectBorder.Height ;
      }
  }

   public double CtlWidth
   {
      get { return _root.Width; }
      set
      {
           double currentPercentage = Percentage;
           _root.Width = value;
           ProgressRectBorder.Width = _root.Width = ProgressRect.Width = value;
           UpdateInfoPos();
           UpdateUI(currentPercentage);
      }
   }

   public double Percentage
   {
        get { return (ProgressRect.Width / _root.Width) * 100.0; }
        set {  UpdateUI(value > 100 ? 100 : value); }
   }

   private void UpdateInfoPos()
   {
        double leftPos = (_root.Width - Info.ActualWidth) / 2;
        Info.SetValue(Canvas.LeftProperty, leftPos);
   }

   private void UpdateUI(double currentPercentage)
   {
     ProgressRect.Width = (currentPercentage * _root.Width) / 100.0;
     Info.Text = string.Concat(currentPercentage, "%");
   }

   private Rectangle ProgressRect
   {
     get { return (Rectangle)_root.FindName("fill"); }
   }

   private Rectangle ProgressRectBorder
   {
      get { return (Rectangle)_root.FindName("border"); }
   }

   private TextBlock Info
   {
      get { return (TextBlock)_root.FindName("info"); }
    }
  }
}

Nothing too fancy as you can see, but there are still some observations that need to be made:

  • I've added CtlWidth and CtlHeight because newing the Witdh and Height properties doesn't work from XAML, ie, redefining the width and height properties only lets you define the width/heighr from your codebehind file. If you try to set those properties from your XAML file, it won't work;
  • I've added private fields to simplify access to the named objects defined on the XAML file;
  • The current percentage is calculated by comparing the width of the rectangle against the width of the canvas that hosts it.

As you can see, the code for a progress bar is really simple and you only need to pay attention to some details (like the Width/Height problem i've mentioned).

by luisabreu | with no comments
Filed under:
Silverlight: error code explained
Tue, Jul 24 2007 23:09

A cool reference about the errors you might get on silverlight pages can be found here. Enjoy!

by luisabreu | 6 comment(s)
Filed under:
Silverlight: the AG_E_RUNTIME_MANAGED_ASSEMBLY_DOWNLOAD error
Mon, Jul 23 2007 22:34

Quick tip: if you have this error, then you've got the wrong name for your assembly in the xmlns namespace introduced on the xaml file. Quick example:

xmlns:la="clr-namespace:Silverlight.Controls;assembly=ClentBin/SilverlightProgressBar.dll"

Notice the ClentBin (instead of ClientBin) typo...

by luisabreu | 3 comment(s)
Filed under:
IronRuby's first source code drop is out
Mon, Jul 23 2007 22:07

And John Lam gives you more info about it here.

Book review: Don't make me think
Sun, Jul 22 2007 22:48

This is really a cool book by Steve Krug. Even though some years have passed since the release of the 1st edition, this second one maintains the level and adds 3 new chapters. The book is very well written and has lots of good advices. Another thing: it's short and you can read it in one or two evenings (i needed two, but I'm a slow reader :) ). If ou haven't read it, then get a copy and read it right now! I'm giving it a 9/10 :)

by luisabreu | with no comments
Filed under:
Silverlight: compensating movement changes on animations
Wed, Jul 18 2007 12:10

Another experience I've run today was related with compensating direction changes on animations. Here's the scenario: suppose you've got a rectangle and you want it to move from x to y when something happens and then from y to x when another thing happens. 

The main problem is that the change in direction might happen before the previous running animations ends. If you want to have a cool effect, you'll have to adjust the duration of the animation so that it looks like its moving smoothly and at the same velocity. Let's start with the XAML:

<Canvas
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Name="parentCanvas"
  Loaded="Page_Loaded"
  x:Class="SilverlightProject2.Page11;assembly=ClientBin/SilverlightProject2.dll"
  Width="640"
  Height="480"
  Background="White">
  <Canvas.Resources>
    <Storyboard x:Name="moveright">
       <DoubleAnimation To="544" Duration="0:0:3" x:Name="moverightanim"
           Storyboard.TargetName="rectangle"
           Storyboard.TargetProperty="(Canvas.Left)" />
   </Storyboard>
   <Storyboard x:Name="moveleft">
       <DoubleAnimation To="16" Duration="0:0:3" x:Name="moveleftanim"
           Storyboard.TargetName="rectangle"
           Storyboard.TargetProperty="(Canvas.Left)" />
   </Storyboard>
  </Canvas.Resources>
  <Rectangle Fill="#FFE81E1E"
        Stroke="#FF000000" x:Name="rectangle" Width="56" Height="48"
        Canvas.Left="16" Canvas.Top="64" />
  <TextBlock Canvas.Left="10" Canvas.Top="200" Text="Left"    MouseLeftButtonDown="StartLeft" />
   <TextBlock Canvas.Left="100" Canvas.Top="200" Text="Right" MouseLeftButtonDown="StartRight" />
</Canvas>

As you can see, nothing too fancy is going on here. I've just added two storyboards which use a double animation to change the value of the Canvas.Left property of the rectangle. Notice that I've only set the To property of each animation. By doing this i know that when an animation begins, it'll start from the current X coordinate (and this might not be the leftmost or rightmost X coordinate).

The TextBlocks are there just to control direction changes. When you click on the Right textblock, the square starts moving to the right side; clicking on the left one makes it move in the other direction. My first attempt to make direction changes looked something like this:

void StartRight(object sender, EventArgs e)
{
    moveright.Begin();
}

void StartLeft(object sender, EventArgs e)
{
    moveleft.Begin();
}

If you try to do that, you'll see that the square changes its moving direction like we want. The problem is that it'll always take 3 seconds to run. This means that if you click right and then left, you'll see that it takes 3 seconds to move from its small offset till it reaches the starting position. It's not what we're looking for! What we need is to dynamically change the duration of the animation so that it's adjusted to the space that the square needs to cover (in one direction or another).

To achieve this purpose, I've started by adding some constants and read only fields:

const double maxPosX = 544;
const double minPosX = 16;
static readonly TimeSpan duration = new TimeSpan(0,0,3);

Then I've build an auxiliary method that calculates the percentage of the distance that the square will cover:

double GetCurrentPercentage(Direction dir)
{
   double currentX = (double)rectangle.GetValue(Canvas.LeftProperty);
   double currentDistance = dir == Direction.ToLeft ? currentX - minPosX : maxPosX - currentX;
   double currentPercentage = currentDistance / (maxPosX - minPosX);
   return currentPercentage;
}

As you can see, we need to know the direction that is being followed. Direction is a simple enumeration that looks like this:

enum Direction
{
  ToLeft,
  ToRight
}

Now we just need to apply it to the maximum duration of the animation when the user clicks left or right:

void StartLeft(object sender, EventArgs e)
{
  long adjustedTicks = Convert.ToInt64(duration.Ticks * GetCurrentPercentage(Direction.ToLeft) );
  moveleftanim.Duration = new TimeSpan(adjustedTicks);
  moveleft.Begin();
}

Moving to the right is similar, so I'll leave it to you :).

by luisabreu | 1 comment(s)
Filed under:
Silverlight: the parenthesis () do matter!
Wed, Jul 18 2007 10:58

Today I needed to animate a Rectangle so that it moved from left to right. Like all sane people, I've right clicked the xaml file and chose open in blend. Building the animation was really a complex operation: I only needed a pair of clicks and the rectangle was moving :) . Unfortunately, the code blend generates sucks a lot. In order to build the animation, it adds several unecessary transforms to the rectangle:

<Rectangle RenderTransformOrigin="0.5,0.5" Fill="#FFE81E1E" 
       Stroke="#FF000000" x:Name="rectangle" Width="56" Height="48"
       Canvas.Left="16" Canvas.Top="64">
      <Rectangle.RenderTransform>
         <TransformGroup>
           <ScaleTransform ScaleX="1" ScaleY="1"/>
           <SkewTransform AngleX="0" AngleY="0"/>
           <RotateTransform Angle="0"/>
           <TranslateTransform X="0" Y="0"/>
        </TransformGroup>
     </Rectangle.RenderTransform>
</Rectangle>

And then it keeps polluting my XAML code by adding the following storyboard:

<Storyboard x:Name="moveright">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
            Storyboard.TargetName="rectangle"
            Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
          <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
          <SplineDoubleKeyFrame KeyTime="00:00:02" Value="544"/>
   </DoubleAnimationUsingKeyFrames>
</Storyboard>

wtf??? Man, i only need a simple animation here! I guess this is what happens when you rely on a tool that has to build all sorts of animations. anyway, this sucked and i though that it was time to clean it up. I started with the xaml for the rectangle:

<Rectangle RenderTransformOrigin="0.5,0.5" Fill="#FFE81E1E"
         Stroke="#FF000000" x:Name="rectangle" Width="56" Height="48"
         Canvas.Left="16" Canvas.Top="64">

I think we all agree that this is all that is needed, right?

Now, the cool part (which is why i'm writing this post): building the storyboard. When you look at the code blend generates, it's obvious that it uses a TranslateTransform to change the position of the element. Again,  it's fair to say that we don't need that to change the position of the rectangle. The only thing we need is to change its Canvas.Left property. With this in mind, I've written the following code (yeah, I've also discarded the key frames animation :) ):

<Storyboard x:Name="moveright">
   <DoubleAnimation To="544" Duration="0:0:3"
         Storyboard.TargetName="rectangle"
         Storyboard.TargetProperty="Canvas.Left" />
</Storyboard>

Surprise! loading it on the browser doesn't do anything! the rectangle didn't even move an inch. What was i doing wrong? well, i was missing a pair of parenthesis! Here's the correct code:

<Storyboard x:Name="moveright">
   <DoubleAnimation To="544" Duration="0:0:3"
         Storyboard.TargetName="rectangle"
         Storyboard.TargetProperty="(Canvas.Left)" />
</Storyboard>

After all, sometimes the parenthesis do matter!

by luisabreu | with no comments
Filed under:
Thinking about building your own AppDomainManager?
Tue, Jul 17 2007 13:28

If yes, then don't forget that it need to run in full trust, so adding it to the GAC is something to keep in mind...at least, that was what i've ended up discovering after spending 2 hours trying to understand why i was getting an exception when the 2nd domain tried to create the custom AppDomainManager i've written. btw, if you're into this type of things, you need to have this.

by luisabreu | with no comments
Filed under:
Silverlight Astoria client add on
Mon, Jul 16 2007 18:31

Pablo Castro announced the Silverlight client add on a few days ago. If you're into Astoria and Silverlight, then go get it!

We need a new release of Siverlight right now!
Mon, Jul 16 2007 12:13

And one where cross-domain calls do work! I'm not a game programmer. I'm not even a designer. so, many of the features available are of no good to me. Cross-domain calls are off, which means that I cannot build components which agregate info from different domains. It really sucks! Please, help ups and release a new version with cross-domain support! And, since i'm asking, how about letting us set the bytes of the image and media element objects?

by luisabreu | with no comments
Filed under:
Silverlight: serializing the contents of a web service call
Mon, Jul 16 2007 10:03

Today I've seen an interesting question on the Silverlight forum. The question was: how to change the MaxJsonLenght property of the JavaScriptSerializer object that is used on the serialization of the objects that are passed to the web service?

Answer: well, you need to use the BrowserHttpWebRequest object and create a custom JavaScriptSerializer object. Here's a quick example. Lets start by creating a custom class that is used to return the response of an asmx web service:

public class Test
{
     private string _nome;
     private string _morada;

     public string Nome
    {
         get {  return _nome; }
         set { _nome = value; }
    }

    public string Morada
    {
        get { return _morada; }
        set { _morada = value;}
    }
}

Now, the simple web service:

[WebMethod]
[ScriptMethod]
public Test HelloWorld(string info) {
   Test t = new Test();
   t.Nome = "LKLLL"
   t.Morada = info;
   return t;
}

Pretty simple stuff...Now, the interesting stuff: the code you need to use to call the web service:

Test ret;
string path = "WebService.asmx/HelloWorld"
using (BrowserHttpWebRequest request =
       new BrowserHttpWebRequest(new Uri(path, UriKind.Relative)))
{
    request.ContentType = "application/json"
    request.Method = "POST"
    HttpWebResponse response = null;
    using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
    {
         StringBuilder str = new StringBuilder();
         str.Append("{");
         str.Append("\"info\":");
         JavaScriptSerializer converter = new JavaScriptSerializer();
         converter.Serialize("address", str);
         str.Append("}");
         writer.Write(str.ToString());
         writer.Flush();
         response = request.GetResponse();
   }
   if (response.StatusCode != HttpStatusCode.OK
   {
       //check for error and inform user 
   }
   using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  {
      JavaScriptSerializer converter = new JavaScriptSerializer();
      string json = reader.ReadToEnd();
      ret = converter.Deserialize<Test>(json);
      if (ret != null)
      {
          Debug.WriteLine(ret.Nome);
          Debug.WriteLine(ret.Morada);
      }
      else
     {
         Debug.WriteLine("ret is null");
     }
  }

}

Important things to retain from the demo sample:

  • Don't forget to add the name of the method you're calling to the url;
  • When you're using JSON as the serialization format, you must set the  content type to application/json;
  • I really didn't need to use the serializer to serialize the string; i could simply add it to the string builder but I've opted for using the serializer for demonstrating purposes;
  • You really need to get a reference to the response from within the StreamWriter using block;
  • Deserializing the return result is easy: you just need to get the JSON string and pass it to the generic Deserialize method.
by luisabreu | 1 comment(s)
Filed under:
CTRL+ALT+DEL through remote desktop
Fri, Jul 13 2007 9:05

In the last days I've been working over remote desktop and today i've needed to send CTRL+ALT+DEL to the remote machine. I've ended up discovering (by pure luck, I must say) that you get the same menu by using the combination CTRL+ALT+END...

by luisabreu | 2 comment(s)
Filed under:
Silverlight: Beta vs Alpha
Thu, Jul 12 2007 23:27

Sorry, but to me only the manged version matters :) Just for fun i've tried porting some of the beta samples to managed code. Against all odds, i've ended up enjoying the simplicity of Javascript and I've tested different approaches for encapsulating xaml content. When i ported the beta samples, i wanted to do it as quickly as possible.

So, i've just copied the xaml and built the rest of the code around those files instead of refactoring the main elements of the top canvas into controls. And you want to know something? I've really think that this approach might be a good option if you're not repeating elements on a canvas (at least on the current version).

Btw, there are really somethings which are a lot easier in javascript than in managed code. For instance, try setting a path in managed code and then see how easy it's in Javascript...If you take a look at the code i've written in managed code, you'll see that some don't mimic all the functionalities that exist on beta version's code (most of them for lack of time).

8C Competizione
Thu, Jul 12 2007 21:38

If you're into cars, then it's impossible not to like the Alfa Romeo 8C Competizione...My good friend Alberto sent me this link with some cool desktop pictures of the car. This is my favourite one.

by luisabreu | 8 comment(s)
Filed under:
Silverlight: Dowloading several images packaged on a ZIP file
Tue, Jul 10 2007 23:40

One of the things you can in your Silverlight apps is package several items on a zip file and then download them through the Downloader object. Packaging several files and compressing them might increase your app's performance, so this is something you should do whenever you can. Let's run through a custom example. Let's suppose we've got 2 pics called car.jpg and car2.jpg which are packaged on a zip file called test.zip. You can start by downloading the zip file by running the following code:

Downloader d = new Downloader();
d.Open("GET", new Uri("tests.zip", UriKind.Relative), true);
d.Completed += new EventHandler(d_Completed);
d.Send();

Now, let's also suppose that our xaml page has an image (called img) and you want it to show the car2.jpg photo. No problem: that's why you have the SetSource method! This method receives a downloader and a string, which lets you set the part name. The part name is used when you download a zip package and is just the name of the file from within the package you've just downloaded:

void d_Completed(object sender, EventArgs e)
{
    img.SetSource((Downloader)sender, "car2.jpg");
}

Yes, that is really all you have to do!

by luisabreu | with no comments
Filed under:
Silverlight alpha gotchas
Tue, Jul 3 2007 22:16

[Update: I must have been drinking when i wrote this :) It should be local domain because you cannot get objects from a remote host through the BrowserHttpWebRequest]

These 2 just made me loose +45 minutes:

1. if you're using the BrowserHttpWebRequest to download files from a remote domain, then make sure you're testing your page from a web server (the internal server that comes with VS works, but you'll start getting the object is not on the correct state exception -or something like that - if you try accessing objects from a remote host).

2. The same holds true if you're loading a remote wmv file on a MediaElement.

Not sure if there's any explanation for these, but it did steel me 45 precious minutes.

Book review: Designing Interactions
Tue, Jul 3 2007 21:35

Another book on usability that gives you different perspectives on this subject. It gives you a nice historical perspective on several aspects related with design with are accompanied by several interviews (which are recorded on DVD). Lots and lots of cool stories on it. That's the positive part!

Now, the book isn't really a pearl, why?  The main problem i see with it is that it turns around IDEO (a company owned by the author of the book) and it seems like he wastes too much time praising the company. well, I'm not saying that the company sucks. what i'm saying is that it gets a little boring reading chapter after chapter that IDEO is really cool and has lots of bright people. oh, still a good read, but no more than 6/10.

by luisabreu | with no comments
Filed under:
Buying a new toy
Mon, Jul 2 2007 17:15

One of the things i did last week (while the site was done) was buying a new camera. I really didn't need anything too fancy, but I wasn't interested in getting the cheapest of the store too. so, I've ended up buying a Canon Powershot S3. I've been running several experiences with it and I must say that until now I'm really enjoying it.

One of the things that impressed me was the canon stich support (ie, it's really easy to take several photos and then stich them so that it turns into a big photo). It's really cool and appropriate for an apprentice like me :)

by luisabreu | 6 comment(s)
Filed under:

Search

This Blog

Tags

Community

Archives

Syndication

Email Notifications

News




  • View Luis Abreu's profile on LinkedIn


    Follow me at Twitter

    My books

    Silverlight 4.0: Curso Completo

    ASP.NET 4.0: Curso Completo

    Portuguese LINQ book cover

    Portuguese ASP.NET 3.5 book cover

    Portuguese ASP.NET AJAX book cover

    Portuguese ASP.NET AJAX book cover