Expression based Property Getters and Setters

April 28, 2013


Many times I need to get or set properties on a class dynamically, i.e.
not knowing their exact names at the compile times. Usually I was doing it
using System.Reflection API’s PropertyInfo
class. This class provides GetValue() and
SetValue methods that allow extrating or setting
a value of a C# property based on the the propertie’s name.
The problem with this approach is that accessing a property dynamically
using reflection API is very slow in comparison to accessing it
via usual static API – in my tests the difference was more than 60-fold.

I thought about using LINQ’s expression trees, instead. Nice thing about the
expression trees is that they can be compiled in a way very similar to
static compilation. It turned out that there are already examples of
Expression getters and setters available on the internet e.g. from
Using expression trees to get property getter and setters and Creating a property setter delegate.

Based on the code described at the above URL, I built my own little
Expression based getter and setter library:

// returns property getter
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");

    Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Func<TObject, TProperty> result =
        Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();

    return result;
}

// returns property setter:
public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
{            
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));

    ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);

    MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
    (
        Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
    ).Compile();

    return result;
}

I also did some benchmarking comparing the speed of these getters and setters to those of

  1. Direct statically compiled code setting and getting the properties
  2. Statically compiled lambdas
  3. Reflection based property getting and setting

Here are the results of running the getters and setters on 100000000 different objects with
string properies:

Getters

Time (seconds) Getter Type
0.4 Direct Statically Compiled
0.64 Statically Compiled Lambda
2.0 Compiled Expression based Getter
36.5 Reflection based Getter

Setters

Time (seconds) Setter Type
0.7 Direct Statically Compiled
1.0 Statically Compiled Lambda
2.4 Compiled Expression based Setter
50.6 Reflection based Setter

You can see, that even though the dynamically compiled expressions are 3-5 times slower than
statically compiled direct methods and 2-3 times slower than statically compiled lambdas,
they are 18-20 times faster than Reflection based approach.

The code for the demo is located under CompiledExpressionTests.zip

Advertisement

Binding without WPF

March 31, 2013


This article is originally published at nickssoftwareblog.com

I was saying before that WPF introduced a lot of concepts that are actually bigger than WPF and can be applied to purely non-visual objects.

Here we are going to talk about the binding concept and how it can be re-implemented outside of the WPF without being tied to the visual libraries or the UI threads. We are going to talk about property and collection bindings.

Property bindings are quite similar to the usual WPF bindings – a change of a property on one object can trigger a change of a different property on a different object.

Collection bindings are also present in WPF but only implicitly. You’ve come across them  if you dealt with various descendants of the ItemsControl class. ItemsControl has ItemsSource property that should be set to a collection of (usually) non-visual objects. When you supply an ItemTemplate or an ItemTemplateSelector, you essentially specify how to turn those non-visual objects into the visual ones. The resulting visual objects can be e.g. of ListBoxItem or ListViewItem type etc. The ItemsSource collection is bound with the resulting collection of visual objects so that when you add or remove the items from the one of them, the corresponding items are also added or removed from the other. Here we discuss creating a similar binding between non-visual collections.

Why would someone need a binding without WPF? Actually there are a lot of situations where you want different parts of your application (visual or not) to change in sync. Here are just a few examples:

  1.  Assume that you use an MVVM pattern. Your view model has a collection that consists of different items. Each item is similar to corresponding items from the model, but have some view specific properties added (e.g. IsVisible, IsEnabled etc). You want you view model to be totally in sync with the model without much extra code. Actually you can use the non-visual binding to achieve that.
  2. Using bindings you can can easily create an observer pattern, with one a bunch of objects having two way bindings to a single (observable) object, so that when one of them changes, the rest are updated via the observable object.
  3. When you do not have access to WPF functionality e.g. if you are programming Objective-C or some other language for a different platform, you can use the generic binding to bind visual parts of the application to the non-visual code, similar to the way it is done in WPF.

The library containing the binding code can be downloaded from NP.Binding.Utils.zip.
Its capabilities are better shown by the samples which can be downloaded from BindingSamples.zip.

The simplest sample showing how to bind two properties together is located under PropToPropBindingTest solution. The main program of the solution, shows how to create two objects with and bind them so that if the property on the first object changes, the property on the second object changes too. Here is the source code of the Main function:

static void Main(string[] args)
{
    AClassWithBindindableProperty a1 = new AClassWithBindindableProperty();

    AClassWithBindindableProperty a2 = new AClassWithBindindableProperty();

    a2.OneWayBind("ABindingProperty", a1, "ABindingProperty");

    a1.ABindingProperty = "1234";

    Console.WriteLine(a2.ABindingProperty);
}

The code above creates two objects a1 and a2 of AClassWithBindindableProperty type and uses OneWayBind() utility function to bind their ABindingProperty properties together. The source object is a1 and the target object is a2. AClassWithBindindableProperty class implements INotifyPropertyChanged interface and ensures that its PropertyChanged event fires when the corresponding property changes. Note that unlike in WPF, the target property does not have to be a dependency property on a dependency object. Also note, that in order to prevent the circular updates, the implementation of the property setter ensures that the PropertyChanged event does not fire if the new property value is the same as the old one.

The binding method OneWayBind is a static extension method defined within BindingUtils static class within NP.Binding.Utils library. It creates a OneWayPropertyBinding object, sets its parameters and calls its Bind method. The OneWayPropertyBinding uses reflection to bind the source property to the target property. If, at some point, you want to remove the binding, you have to save the OneWayPropertyBinding object and later call UnBind() method on it.

Note that classes representing different types of bindings (with OneWayPropertyBinding among them) implement IBinding interface that has 3 methods:

  1. Bind(bool doInitialSync=true) – creates a binding within an option to skip initial synchronization of the bound objects (or properties).
  2. UnBind() – removes a previously created binding.
  3. InitialSync() – Synchronizes the bound objects after the binding has been created (e.g. in case of property binding, it usually means setting the target property to equal the source property when the binding is established (even if the source property did not change at that time)

Note, that OneWayPropertyBinding class TheConverter property allowing to set the binding’s converter ensuring that the target property can be different from the source one.

The next sample to consider is located under OneWayCollectionBindingTest solution. It shows how to use OneWayCollectionBinding class to bind two different collections, so that when the source collection changes (i.e. has elements added or removed or moved) the target collection undergoes similar changes.

Here is the code from the sample’s Main function:

static void Main(string[] args)
{
    // create source collection elements to be integers from 1 to 20
    ObservableCollection source =
        new ObservableCollection(Enumerable.Range(1, 20));

    List target = new List();

    // create the binding
    OneWayCollectionBinding myBinding =
        new OneWayCollectionBinding
        {
            SourceCollection = source,
            TargetCollection = target,
            SourceToTargetDelegate = (i) => i + 100 //set each target element to be 
                                                    // 100 + corresponding source element
        };

    // bind
    myBinding.Bind();

    // remove 5th element from the source
    source.RemoveAt(5);

    // move source element at position 1 to position 4
    source.Move(1, 4);
    Console.WriteLine("\n\nSOURCE");
    source.ForEach(Console.WriteLine); // print the resulting source elements

    Console.WriteLine("\n\nTARGET");
    target.ForEach(Console.WriteLine); // print the resulting target elements
}

Running this code will result in source and target elements being in sync in spite of the source collection manipulations (we removed the element from position 5 in it and moved the element at position 1 to position 4). SourceToTargetDelegate of the OneWayCollectionBinding class allows to specify conversion between the source and target collection elements (in our sample we simply add 100 to the source element in order to obtain the target one). We use OneWayCollectionBinding with one generic argument – int (meaning that the source and target collection elements are of the same time int. In fact we can use OneWayCollectionBinding with two different generic arguments e.g. OneWayCollectionBinding<int, string> allowing the source and target elements to be of different types. In that case SourceToTargetDelegate will produce an object of the target type out of the source type object.

In case of a property-to-property binding we used comparison of the new and older property values in order to make sure that we avoid an infinite updating loop. Unfortunately we cannot resort to a similar check in can of the collection bindings. The full solution for preventing the infinite loops for circular bindings is beyond this article and will be presented later. Here, however, we can make sure that the binding action is only called once by using _doNotReact field and DoNotReact property. We can also pass the information that the binding is acting at this point in time to an external entity by using OnDoNotReactChangedEvent event. This is important for create two way bindings. Note that the source collection for collection binding should always be an ObservableCollection.

The final sample (TwoWayCollectionBindingTest) demonstrates a two way collection binding when the source and target collections are in perfect sync, i.e. changes to any of them will result in the corresponding changes in the other. Here is the Main for the sample:

static void Main(string[] args)
{
    ObservableCollection<int> sourceCollection =
        new ObservableCollection<int> { 1, 2, 3 };

    ObservableCollection<string> targetCollection =
        new ObservableCollection<string>();

    TwoWayCollectionBinding<int, string> twoWayBinding = 
        new TwoWayCollectionBinding<int, string>
        {
            SourceCollection = sourceCollection,
            TargetCollection = targetCollection,
            SourceToTargetDelegate = (i) => i.ToString(),// specifies how to create target 
                                                            // elements out of source ones
            TargetToSourceDelegate = (str) => Int32.Parse(str) // specifies how to create source 
                                                                  // elements out of target ones
        };

    twoWayBinding.Bind();

    Console.WriteLine("After removing element at index 1");
    sourceCollection.RemoveAt(1); // remove element at index 1 from source collection
    targetCollection.ForEach((str) => Console.WriteLine(str)); // print target collection

    Console.WriteLine("After adding 4");
    targetCollection.Add("4"); // append string "4" to the end of the target collection
    sourceCollection.ForEach((i) => Console.WriteLine(i)); // print the source collection

    Console.WriteLine("After inserting 0");
    targetCollection.Insert(0, "0"); // insert string "0" at index 0 for the target collection
    sourceCollection.ForEach((i) => Console.WriteLine(i)); // print the source collection

    Console.WriteLine("After inserting 2");
    sourceCollection.Insert(2, 2); // insert number 2 at index 2 for the source collection
    targetCollection.ForEach((str) => Console.WriteLine(str)); // print the target collection
}

Both source and target collections have to be of ObservableCollection type (both should fire
CollectionChanged event when the collection content changes). Note that the source and target elements are of different types within this sample: the source elements are of type int while the target elements are of type string. SourceToTargetDelegate and TargetToSourceDelegate specify how to create a target element from a source element and vice versa.

There were a couple of challenges in creating TwoWayCollectionBinding:

  1. What to do about initial synchronization of the two collection. To resolve this challenge, in our implementation we assume that the target collection is empty before the binding and is populated by the elements corresponding to all the elements of the source collection during the binding.
  2. Avoiding a loop when updating the collection. We implement TwoWayCollectionBinding as two one way bindings (_forwardBinding and _reverseBinding). When one of them fires, the other should not be triggered in within the same update. We use OnDoNotReactChangedEvent to achieve that.

There are many binding related issues that were left open in the article and in the current implementation:

  1. Our binding updates are all done in the same thread – current implementation does not have a way to control the thread. 
  2. Complex collection binding connections can lead to the undetected binding loops.
  3. In WPF, bindings can be very elegantly expressed in XAML. Our bindings so far cannot do the same.
  4. WPF bindings can be specified by a path or a name of an element within XAML or an ancestor element within the visual tree. Our bindings, so far cannot do it.

I plan to address all these issues in the future publications.

A great WPF localization package

March 17, 2013


Several months ago I needed to localize a WPF application (it had to have English and German versions). I found an excellent localization package for WPF on the internet and used it for my project. The package was created by Tomer Shamam  and was described at WPF Localization – On-the-fly Language Selection (though the link is no longer available). I published the code for the package (kindly sent to me by Tomer) on github at WPFLocalizationPackage.

It proved to be a great solution allowing to create a German version very fast.

The package is open source, allows switching the locales at run time and also allows localizing any Dependency or Attached properties – not only strings. It provides “Translate” markup extension that can be used from within XAML.

In order to localize an application with the help of this package, you need to create XML catalogs for each of the locales you want your application to support. Here is an excerpt from such catalog that comes with the demo that comes together with the source:

<Dictionary EnglishName="English" CultureName="English" Culture="en-US">
<Value Id="0" FlowDirection="LeftToRight" 
             Title="Demo Window" 
             Width="700" Height="340" />
<Value Id="1" Content="This is a simple text" />
...
<Dictionary>

Each Value tag has an Id attribute used for matching values from the catalogs into XAML or C# code. The rest of the attributes specify WPF object properties and values that those properties should get under the locale.

Here is an example of referring to a catalog value from XAML code:

<Window ...
Title="{loc:Translate Title, Uid=0}"
...
>

Translate markup extension refers to attribute title under Value tag with Id=0.

Mapping between the different cultures and catalogs is done with the help of LanguageDictionary.RegisterDictionary method, e.g.:

LanguageDictionary.RegisterDictionary(
CultureInfo.GetCultureInfo("en-US"),
new XmlLanguageDictionary("Languages/en-US.xml"));

LanguageDictionary.RegisterDictionary(
CultureInfo.GetCultureInfo("he-IL"),
new XmlLanguageDictionary("Languages/he-IL.xml"));

maps culture “en-US” into en-US.xml catalog file under Languages folder while culture “he-IL” is mapped into he-IL.xml file

Here is the code to change localization catalog at run time:

if (LanguageContext.Instance.Culture == CultureInfo.GetCultureInfo("he-IL"))
{
LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo("en-US");
}
else
{
LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo("he-IL");
}

The demo contains an application that can switch between English and Hebrew locales. Here is how the English version looks:

LocaleAppEnglish

And here is its Hebrew counterpart:

LocaleAppHebrew

You can switch between English and Hebrew by pressing the button with the corresponding flag. As you can see not only strings, but also sizes and (even more impressively) the FlowDirection changes when the locale is switched.

Please find more info at the WPF Localization – On-the-fly Language Selection and by browsing the demo code.

Restarting the blog.

March 15, 2013

Hi All,

This blog has been dead for a while and I was posting technical articles mainly on codeproject.com.

I plan to restart this blog posting programming tit-bits and software-related ideas on it while still publishing longer articles on codeproject.com.

New articles on Silverlight and Prism

February 21, 2011

It has been a while and I kind of neglected the blog, but I did publish a bunch of new articles on code project:

Prism for Silverlight/MEF in Easy Samples. Part 1 – Prism Modules

Prism for Silverlight/MEF in Easy Samples. Part 2 – Prism Navigation

Prism for Silverlight/MEF in Easy Samples. Part 3 – Communication between the Modules

Silverlight Animations along Arbitrary Mathematical Paths via Easing

Parameter Substitution within Expression Trees

Silverlight 2.0 In Examples: Part ? Drag and Drop Inside Out

October 7, 2008

Introduction

This is a continuation of a tutorial, see Silverlight 2.0 In Examples: Part 0. Introduction” and “Silverlight 2.0 In Examples: Part 1. Silverlight Elements: Panels and Controls.

Since recently I’ve been working on Silverlight Drag and Drop, I decided to break the continuity of this tutorial and skip several parts, writing right away about how to implement Drag and Drop in Silverlight. In addition to information from the previous sections of the tutorial, this part requires some knowledge of DataTemplates and binding (I will give brief explanations of both).

The article that started me on Silverlight 2.0 Drag and Drop can be accessed via the following link: Drag and Drop in Silverlight. At the bottom of the article you can find a link to download the source code.

Here, however, I go over Drag and Drop with more details and examples. A special feature of this article is a Drag and Drop custom control designed to absorb most of the Drag and Drop complexity. Based on this control, I created an example functionally similar to the one described in Drag and Drop in Silverlight.

Silverlight demos, including those corresponding to the samples presented here can be found at AWebPros Demos.

Simple Silverlight Drag and Drop Example

Here is the screen capture of the first example:

One can drag and drop the red circle anywhere within the Silverlight application area.
The source code for this sample can be downloaded from simpledragdropzip.doc. As always, please remove .doc extension, rename the file to simpledragdrop.zip and then open it as a zip file.
Below the code of the sample is explained in detail.
Here are the contents of Page.xaml file:

<UserControl

    x:Class=”SimpleDragDrop.Page”

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

    Background=”Yellow”

    Width=”400″

    Height=”300″>

    <UserControl.Resources>

        <DataTemplate x:Key=”Circle”>

            <Ellipse Width=”20″ Height=”20″ Fill=”Red”></Ellipse>

        </DataTemplate>

    </UserControl.Resources>

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

        <Popup x:Name=”MyPopup”IsOpen=”False”>

            <ContentControl

   ContentTemplate=”{StaticResource Circle}”

   Opacity=”0.5″/>

        </Popup>

        <ContentControl

            ContentTemplate=”{StaticResource Circle}”

            x:Name=”MyControlToMove”>

        </ContentControl>

    </Grid>

</UserControl>
The object that we are dragging and dropping is ContentControl at the very bottom of the XAML file. Its name is “MyControlToMove”.

ContentControl is a control that has two major properties: Content (which contains some data) and ContentTemplate (which specifies how to present this data).

In our case the presentation of MyControlToMove is not data dependent (Content property does not play any role). This presentation is determined only by the DataTemplate which is defined as a resource called “Circle” within UserControl.Resources section. In this example this ContentControl is always displayed as a red circle.
Another control is used as a drag cursor to show where the circle is dragged. It is represented by a similar red circle with its opacity property set to 0.5, making it semitransparent. This control is of Popup type.

Now, let us deconstruct the C# code. While XAML contains mostly design and static information, C# carries information about actions. There are 3 main actions within the Drag and Drop process:

  • Drag beginning – occurs when the left mouse button is pressed on a draggable object.
  • Drag process – occurs when the mouse pointer is moved with the left mouse button still pressed.
  • Drop – occurs when the left mouse button is released.
  • Correspondingly, we have 3 event handlers for 3 events:

  • MouseLeftButtonDown – to handle start of the drag process
  • MouseMove – to handle visual moving of the dragged item
  • MouseLeftButtonUp – to handle drop operation
  • All of the events are registered with the top level panel “LayoutRoot”. This is possible because of the event “Bubbling”. Even if a child of “LayoutRoot” panel is clicked, the event eventually “bubbles” up to it, unless it is handled before.
    Here is how we set the event handlers within the application:

    LayoutRoot.MouseLeftButtonDown +=

        new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonDown);

    LayoutRoot.MouseMove +=

        new MouseEventHandler(LayoutRoot_MouseMove);

    LayoutRoot.MouseLeftButtonUp +=

        new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);

     

    Now let us describe these 3 operations in detail.

    Starting the Drag Operation

    Starting the drag operation is handled by the function LayoutRoot_MouseLeftButtonDown which in turn calls StartDragDrop.

    Here is the code for LayoutRoot_MouseLeftButtonDown function:

    void

    LayoutRoot_MouseLeftButtonDown(object sender,

                                                   MouseButtonEventArgs e)

    {

        // obtain all UI elements at the

        // current mouse pointer location

        List<UIElement> elements =

           (List<UIElement>)this.HitTest(e.GetPosition(null));

     

        // get the first element of type Ellipse and

        // start drag operation on it.

        foreach (UIElement element in elements)

        {

            if (element is Ellipse)

            {

                StartDragDrop(element, e);

                break;

            }

        }

    }

    First HitTest gets all the elements “pierced” by the current mouse pointer. Then we iterate over each of of the elements, find the “Ellipse” (this is our circle we want to move) and start drag operation on it by calling StartDragDrop function.

    Here is the StartDragDrop function code:

    private void

    StartDragDrop(UIElement element,

                  MouseButtonEventArgs e)

    {

        // make the popup visible

        MyPopup.IsOpen = true;

     

        // make the mouse events connected to

        // the popup

        MyPopup.CaptureMouse();

     

        // figure out the mouse coordinates at the onset

        // of Drag operation.

        _horisontalOffset = e.GetPosition(null).X;

        _verticalOffset = e.GetPosition(null).Y;

     

        // set _captured flag to true

        // (this is to check later if drag drop

        //  operation is in progress)

        _captured = true;

     

        // move the popup to the current mouse location.

        MyPopup.HorizontalOffset = _horisontalOffset;

        MyPopup.VerticalOffset = _verticalOffset;

    }

    The StartDragDrop functionality is explained in the comments within its code.

    Drag Operation During the Mouse Move

    Here is how we implemented Drag operation when mouse moves:

    void

    LayoutRoot_MouseMove(object sender,

                         MouseEventArgs e)

    {

        // if no drag and drop started,

        // we do not need to do anything.

        if (!_captured)

            return;

     

        // update the popup location to the

        // current mouse pointer location.

        MyPopup.HorizontalOffset = e.GetPosition(null).X;

        MyPopup.VerticalOffset = e.GetPosition(null).Y;

    }

    All we need to do is to move the Drag popup to the current location of the mouse pointer. 

    Drop Operation

    Finally, here is the function in charge of Drop operation:

    void

    LayoutRoot_MouseLeftButtonUp(object sender,

                                 MouseButtonEventArgs e)

    {

        // if drag is not started we do not need

        // any drop functionality to execute

        if (!_captured)

            return;

     

        // mouse capture is released

        MyPopup.ReleaseMouseCapture();

     

        // popup becomes invisible

        MyPopup.IsOpen = false;

     

        // set captured flag to false

        // (no drag operation in progress)

        _captured = false;

     

        // the rest of the code just moves

        // our content control to the new location

        // using TranslateTransform

        GeneralTransform gt =

            this.TransformToVisual(MyControlToMove);

     

        PointstartPoint = gt.Transform(new Point(0, 0));

     

        Pointp = e.GetPosition(null);

     

        TranslateTransformtt = new TranslateTransform();

     

        tt.X = p.X – _horisontalOffset – startPoint.X;

        tt.Y = p.Y – _verticalOffset – startPoint.Y;

     

        MyControlToMove.RenderTransform = tt;

    }

    As you can see, we stop the DragDrop operation by releasing the mouse capture, making the Drag popup invisible and setting _captured flag to false. Then we do the actual drop operation by moving the original dragged control to the new location using TranslateTransform.

    Drag and Drop with Forbidden Area

    Now, let us consider a more complicated example.
    In addition to the previously discussed functionality it has the following:

  • Area in which it is forbidden to drop.
  • A special template for the Drag popup to appear when the mouse pointer is in the area in which it is forbidden to drop.
  • The drag operation does not start right away, but only when the mouse is far enough from the origin.
  • Here is the screen capture for the example:

    The yellow circle signifies the area where the drop is allowed. Outside of it, the drop is forbidden.
    Here is the code for the example: dragdropwithforbiddenareazip.doc.
    As one can see from the code, the capture process now begins during MouseMove action and only when the distance between the original and current locations of the mouse is greater than _captureRadius:

    private void BeginCapture(MouseEventArgs e)

    {

        // check if the mouse pointer position

        // within _captureRadius

        double diffX =

            e.GetPosition(null).X – _horisontalOffset;

        double diffY =

            e.GetPosition(null).Y – _verticalOffset;

     

        // if it is within _captureRadion,

        // do not start capture

        if ((diffX * diffX + diffY * diffY) <

            _captureRaduis * _captureRaduis)

        {

            return;

        }

     

        // make popup visible

        MyPopup.IsOpen = true;

     

        // capture mouse

        MyPopup.CaptureMouse();

     

        // set _captured flag to true.

        _captured = true;

    }

    There is also a function InAllowedArea that returns true if the mouse pointer is within an area in which we are allowed to drop and false otherwise:

    // checks if drop is allowed

    // at the current location of the

    // mouse pointer.

    bool InAllowedArea(MouseEventArgs e)

    {

        Point p = e.GetPosition(null);

        IEnumerable<UIElement> hitTestResult =

      AllowedArea.HitTest(p);

     

        // see if mouse pointer hits AllowedArea

        // if yes, return true,

        // if no, return false.

        return(hitTestResult.Count() != 0);

    }

    Then, during the Drag process, we check if we are within the area in which we are allowed to drop and set the ContentTemplate of the PopupControl correspondingly:

    if(InAllowedArea(e))

    {

        // if we are in an area

        // in which we are

        // allowed to drop

        // set the template accordingly

        // to our Circle

        PopupControl.ContentTemplate = CircleTemplate;

    }

    else

    {

        // if we are in an area in which it

        // is forbidden to drop, set

        PopupControl.ContentTemplate = DropForbidden;

    }

     

    Generic Drag and Drop Control

    Based on the above examples and also taking into account that the Drag popup display can be data driven (as will be shown later) I came up with a generic Drag/Drop control implementation. While it is still rather complex to use, since drag and drop is a complex operation, it also absorbs a lot of complexity into itself, eliminating the need to implement and debug a large chunk of the Drag/Drop functionality over and over again.

    Here is the code for generic Drag/Drop control together with a couple of samples showing how to use it: genericdragdropzip.doc.

    DragDrop control is defined within GenericDragDropLib project within DragDropControl.cs file. The generic.xaml file contains default control template for DragDropControl.
    DragDropControl contains a number of properties and events that allow customization of the Drag/Drop functionality. Here is the list of these properties and events with the explanations as to why they are needed.

    // mouse is captured and the popup

    // indicating the beginning of Drag

    // operation to the user becomes

    // visible on when the distance between

    // the mouse pointer and the original

    // point when the mouse button was pressed

    // during the Drag operation is

    // greater than CaptureRadius.

    public doubleCaptureRadius { get; set; }

     

    // the popup to show during Drag operation

    public Popup DragDropPopup { get; set; }

     

    // The content control within the DragDropPopup

    // that can assume any shape defined by

    // its data template and date content.

    public ContentControl PopupContentControl { get; set; }

     

    // default data template for areas in

    // which drop is allowed

    public DataTemplate DropAllowedTemplate { get; set; }

     

    // data template for areas in which

    // drop is forbidden

    public DataTemplate DropForbiddenTemplate { get; set; }

     

    // element to be dragged

    public UIElementDraggedElement { get; set; }

     

    // dragged business logic object

    // (specified by Content property of DraggedElement)

    public objectDraggedObject { get; set; }

    // DragContainer property is used when DraggedElement is

    // one of the items within and ItemsControl e.g. a

    // ListBox this property contains the reference to this

    // container control of the dragged item

    public UIElementDragContainer {get; set;}

     

    // does the drop operation

    public event DoDropDelegateDoDrop = null;

     

    // used to filter in the element that can be

    // dragged

    public event IsDraggableDelegateIsDraggable = null;

     

    // used to filter in the container of the element

    // that can be dragged

    public event IsContainerDelegate IsDragContainer = null;

     

    // returns true if, during the drag operation,

    // the mouse pointer is inside the area

    // it which drops are allowed, false otherwise.

    public event IsInAllowedAreaDelegateIsInAllowedArea = null;

     

    // returns data template for the case when the drops are

    // allowed during the drag operation

    public event GetDataTemplateDelegate GetDataTemplate = null;

     

    //used to set the DraggedObject from the

    // DraggedElement.

    // Most of the times, this is just DraggedElement.Content

    public event GetBusinessLogicObjectDelegate

        GetBusinessLogicObject = null;

     

    // used to record the origin of the drag operation

    public Point StartDragPoint { get; set; }

    DragDropControl also contains three functions that need to be triggered by the Button Down, Mouse Move and Button Up events of the application that uses DragDropControl. These functions are

  • StartDragDrop
  • OnMove
  • OnButtonUp
  • Below we describe two examples using DragDropControl.

    Drag Drop with Forbidden Area Implemented Using DragDropControl

    The solution for this test is called GenericDragDropTest.sln and it is located under GenericDragDropTest within genericdragdrop.zip file. It produces exactly the same result as our Drag/Drop with forbidden area example above, but it uses DragDropControl. Below we show how DragDropControl is used.
    Here is the code showing how we connect the events of DragDropControl:

    MyDragDropControl.DoDrop +=

        new GenericDragDropLib.

            DoDropDelegate(MyDragDropControl_DoDrop);

     

    // we only drag ellipses!

    MyDragDropControl.IsDraggable +=

        delegate(UIElement element)

        {

            if (element is Ellipse)

                return true;

            return false;

        };

     

    // data template for the drag popup is

    // provided by CircleTemplate resource

    MyDragDropControl.GetDataTemplate +=

        delegate(UIElement element)

        {

            return (DataTemplate) this.Resources[“CircleTemplate”];

        };

     

    // we are in an area in which are

    // are allowed to drop if the

    // mouse pointer is

    // inside AllowedArea circle.

    MyDragDropControl.IsInAllowedArea +=

        delegate(Point p)

        {

            IEnumerable<UIElement> hitTestResult =

                AllowedArea.HitTest(p);

            return(hitTestResult.Count() != 0);

        };

    And here is the code that connects the mouse button events to the DragDropControl functions:

    // connect the mouse button events to

    // the corresponding functions

    // of our DragDropControl.

    LayoutRoot.MouseLeftButtonDown +=

        delegate(object sender, MouseButtonEventArgs e)

        {

            MyDragDropControl.StartDragDrop(this, e);

        };

     

    LayoutRoot.MouseMove +=

        delegate(object sender, MouseEventArgs e)

        {

            MyDragDropControl.OnMove(e);

        };

     

    LayoutRoot.MouseLeftButtonUp +=

        delegate(object sender, MouseButtonEventArgs e)

        {

            MyDragDropControl.OnButtonUp(e);

        };

    Drag and Drop between Two ListBox Elements

    Here we show an implementation of Drag/Drop analogous to that of Drag and Drop in Silverlight. The ListBoxItem objects are dragged and dropped between two ListBoxes.

    The code for this sample can be found under ListBoxDragDropTest directory of genericdragdrop.zip file.
    Here is the screen capture for this sample:

    This sample also provides an example of having data driven visual presentation of the dragged item (the first and last names of the students provide the data that can change depending on the dragged item).
    Here is the code showing setting the event handlers for DragDropControl events:

    MyDragDropControl.DoDrop +=

        new GenericDragDropLib.DoDropDelegate(DoDrop);

     

    // we only Drag and Drop ListBoxItem objects!

    MyDragDropControl.IsDraggable +=

        delegate(UIElement element)

        {

            if (element is ListBoxItem)

                return true;

            return false;

        };

     

    // our drag container is ListBox

    MyDragDropControl.IsDragContainer +=

        delegate(UIElement element)

        {

            if (element is ListBox)

                return true;

            return false;

        };

     

    // we use the same DataTemplate

    // to display the drag popup as

    // we use to display the items in the list

    MyDragDropControl.GetDataTemplate +=

        delegate(UIElement element)

        {

            ListBoxItemlbi = MyDragDropControl.DraggedElement as ListBoxItem;

     

            if(lbi == null)

                return null;

     

            return (DataTemplate)lbi.ContentTemplate;

        };

     

    // we are in allowed area if and only if we are

    // inside a ListBox

    MyDragDropControl.IsInAllowedArea +=

        delegate(Point p)

        {

            ListBoxlb = GetListBox(p);

            if (lb == null)

                return false;

            return true;

        };

     

    // returns Content property of the ListBoxItem

    MyDragDropControl.GetBusinessLogicObject +=

        delegate(UIElement element)

        {

            ContentControl cc = element as ContentControl;

     

            if (cc == null)

                return null;

     

            return cc.Content;

        };

    One can see that the DoDrop function (called during the drop operation) checks if the target ListBox is not the same as the original ListBox from where the item was dragged and if true, removes the item from the original collection and adds it to the collection of the target ListBox.

    Conclusion

    This article describes the implementation of drag and drop functionality in Silverlight. It starts with a simple example and progresses to more complex ones. It features custom DragDropControl which is used to absorb a lot of complexity of Drag/Drop implementation.

    Silverlight Spy

    September 29, 2008

    By googling for “Silverlight Snoop” (Snoop is a tool for investigating WPF GUI) I came (via jimmangaly.blogspot.com across an interesting tool: Silverlight Spy.

    Make sure you have all prerequisites before installing it.

    Not only it allows you to disassemble and show the composition of your own Silverlight application, but it also allows you to do it to any Silverlight application accessible on the Internet. All you need to do is to type in the url of the page containing that Silverlight application: e.g. I did it for my AWebPros banner typing in “http://awebpros.com/AWebProsMain.aspx&#8221; URL. Then I go to the panel on the right and expand “Silverlight 2 Beta 2 Application (Xaml1)”. Here is the resulting layout:

    Silverlight Spy

    Silverlight Spy

    As you can see, the TextBlock at the top is selected by selecting “textBlock” in the right hand panel!. When I try to select other text blocks, however, they are not shown in the right place – possibly because of the animation. Still it is a very impressive tool.

    Silverlight 2.0 In Examples: Part 1. Silverlight Elements: Panels and Controls

    September 23, 2008

    Introduction

    This is part 1 of the tutorial, but there is also Part 0. You can access it through the following link: Part 0.
    Part 0 of the tutorial was at an introductory level. Here we will switch to the more advanced concepts. In particular, we will assume that the readers are familiar with C# and most of the OO concepts it uses, e.g. inheritance. We will also assume that the readers have some basic knowledge of Visual Studio 2008.

    This installment will include multiple simple examples showing how to use Silverlight elements: panels and controls, while, at the same time displaying the ways Silverlight works.

    Overview of Panels and Controls

    Silverlight 2.0 comes with many built-in objects ready to be used for building a business logic application. Such objects are sub-divided into Panels and Controls.
    Panels are GUI objects that contain other GUI objects (their children object). Practically, any visual object can be placed within a panel: other panels, controls, etc. A panel’s main purpose is to position its child objects.
    Controls usually serve to trigger some business logic behavior of an application or to provide (and change) some business logic values.

    For a comprehensive demo with Silverlight 2.0 Beta 2 controls check the following site.

    Both Panels and Controls derive from FrameworkElement class.
    The figure below desplays a class Hierarchy for Panels and Controls.

    ContentControls have a property “Content” that can be used to contain other controls (not quite true yet for Silverlight 2.0 Beta). ItemsControls are used to display collections of objects. Example of ItemControl is ListBox.

    Controls

    In this section, we are going to consider individual Control examples.

    Button

    Button is a ContentControl whose primary goal is to trigger some business logic when it is clicked. After the click, the usual button comes back to the original state and becomes ready for the next click.

    Here is the source code for a simple project emphasizing the way buttons work: buttonsamplezip.doc. As always, remove the doc extension and rename it to ButtonSample.zip.

    Here is the screen for the project:

    Button Sample

    Button Sample

    Every time you click this button, the number of clicks increases.

    Now, let us discuss the code. As was mentioned in Part 0 of this tutorial, most of the time we do not need modify App.xaml and App.xaml.cs files. So let us take a look at the Page.xaml and Page.xaml.cs files within the solution.
    Here are the contents of Page.xaml file:

    <UserControl x:Class=”ButtonSample.Page”

        xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

        xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

        Width=”400″ Height=”300″>

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

            <Button

                x:Name=”MyButton”

                Width=”150″

                Height=”25″

                Content=”Clicked 0 Times”/>

        </Grid>

    </UserControl>

    One can see a simple button within a Grid. The button has a name (x:Name=”MyButton”). Name is used for accessing this control or element from the C# code (we’ll talk more about it below). It also has its Width, Height and Content properties set. You can play with the button by changing or removing the properties and watching the way the button changes.

    Now, let us take a look at the C# code within the Page.xaml.cs file. Here are its contents: 

    public partial class Page : UserControl

    {

        intnumClicks = 0;

     

        public Page()

        {

            InitializeComponent();

            MyButton.Click += new RoutedEventHandler(MyButton_Click);

        }

     

        voidMyButton_Click(object sender, RoutedEventArgs e)

        {

            numClicks++;

     

            MyButton.Content = “Clicked “+ numClicks + ” times.”;

        }

    }

     

    Take a look at Page() constructor. One can notice that within that constructor we refer to MyButton as if it was a member of the class. Well, in fact, it is a member of the class; we’ve made it so, by naming it “MyButton” within XAML code. Now, all we have to do is to specify the desired behavior when the button is clicked. This is achieved by adding a handler to the “Click” event:

     

    MyButton.Click += new RoutedEventHandler(MyButton_Click);

     

    and by creating the body of the handler as MyButton_Click function:

     

        voidMyButton_Click(object sender, RoutedEventArgs e)

        {

            numClicks++;

     

            MyButton.Content = “Clicked “+ numClicks + ” times.”;

        }

     

    DatePicker

    DatePicker is a control that allows to choose a date. The chosen date is specified by the SelectedDate property of the DatePicker. Here is the source code for DatePicker sample: datepickersamplezip.doc.
    The sample allows the user to choose the date using the DatePicker. Then, whenever the button at the bottom is clicked, the content of the button is changed to the picked date:

    Date Picker Sample

    Date Picker Sample

    Note, that in order to make DatePickerSample compile, we had to add System.Windows.Controls.Extended assembly to the project’s references. This is also reflected within the Page.xaml file by the following line:

    xmlns:extended=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Extended”

    This line makes “extended” to be the XAML namespace for the functionality located within System.Windows.Controls namespace of System.Windows.Controls.Extended assembly.
    Later within the XAML code, we can find DatePicker control by adding “extended:” prefix to it:

    <extended:DatePicker

    x:Name=”MyDatePicker”

          HorizontalAlignment=”Center”

    VerticalAlignment=”Center”>

    </extended:DatePicker>

    Finally, if we look at the C# code, we notice that the Content property of the Button is set to SelectedDate property of the DatePicker:

    DateTime? selectedDate = MyDatePicker.SelectedDate;

     

    if(selectedDate != null)

        MyButton.Content = ((DateTime)selectedDate).ToString();

    ListBox Control

    ListBox is an ItemsControl. Its purpose is to display multiple items as a list. It can have one of the items selected. Here is a very simple example: listboxsamplezip.doc (more complicated examples with binding will be presented in subsequent parts of this tutorial).

    ListBox Sample

    ListBox Sample

    Here is the interesting part of the Page.xaml file:

    <ListBox Width=”100″ Height=”100″>

        <ListBoxItem Content=”Item1″/>

        <ListBoxItem Content=”Item2″/>

        <ListBoxItem Content=”Item3″/>

    </ListBox>

    You can see ListBox containing multiple ListBoxItems. The selected item is referenced by the SelectedItem property of the ListBox.

    Other Controls

    As one can see from Demo Controls there are many other important controls. Since currently I do not have time to provide examples for them all, I am going to briefly describe some of them in this section.

    Border – purely visual control without any specific behaviors. It provides the visual presentation for the border of its content.

    CheckBox – a control with two states: “Clicked” and “Not Clicked”. Its boolean property IsClicked reflects its state.

    GridSplitter – allows resizing the rows or the columns within the GridPanel.

    RadioButton – allows to create groups of mutually exclusive check buttons: if one is in the pressed state, the others are not.

    Slider – slider control. Its Value property specifies how far the slider moved.

    TextBlock – just a way to present the text that cannot be edited by the user. The text string is stored in its Text property.

    TextBox – represents editable text. The text string is reflected by its Text property.

    DataGrid – deserve a special section all to itself. Allows presenting data in table format.

    TabControl – allows presenting multiple screens as tabs within the same window.

    ToolTip – associates a popup message with any control. This message is displayed whenever the mouse is on top of the control.

    Panels

    As was mentioned before, panels are containers of Silverlight visual objects that have a say over where and how the objects are positioned.

    Canvas

    Canvas is a panel that positions its child objects by the coordinates (how much to the right the object is from the left end of the panel and how much down it is from the top).
    The sample code can be downloaded from here: canvassamplezip.doc.
    The figure below, shows a button positioned on top of a Canvas, 200 generic pixels down and 100 to the right.

    Canvas Sample

    Canvas Sample

    The corresponding XAML code is the following:

    <Canvas x:Name=”LayoutRoot” Background=”White”>

        <Button

            Canvas.Left=”100″

            Canvas.Top=”200″

            Content=”Hello World”/>

    </Canvas>

    As you can see, the property Canvas.Left sets the position of the button horizontally and Canvas.Top – vertically.

    StackPanel

    StackPanel allows to put visual objects one after another vertically or horizontally. One can only space out the objects one from another by using their Margin property. Margin consists of 4 numbers specifying in the same order the distance from the left, from the top and the extra space before next element from the right and from the bottom.
    Here is the source code for StackPanel example: stackpanelsamplezip.doc.
    The following figure shows the screen for the sample:

    Stack Panel Sample

    Stack Panel Sample

    The sample includes 2 StackPanels: Vertical and Horizontal. Horizontal StackPanel is placed inside the Vertical one.
    Here is the corresponding XAML:

    <StackPanel

        x:Name=”LayoutRoot”

        Background=”White”>

        <Button

            Width=”200″

            Height=”25″

            Margin=”0,10,0,0″

            Content=”Vertical Button 1″/>

        <Button

            Width=”200″

            Height=”25″

            Margin=”0,10,0,0″

            Content=”Vertical Button 2″/>

        <StackPanel

            Margin=”0,10,0,0″

            Orientation=”Horizontal”>

            <Button

                Width=”150″

                Height=”25″

                Margin=”10,0,0,0″

                Content=”Horizontal Button 1″/>

            <Button

                Width=”150″

                Height=”25″

                Margin=”10,0,0,0″

                Content=”Horizontal Button 2″/>

        </StackPanel>

    </StackPanel>

    One can see that the top level StackPanel has Vertical (default) orientation and contains two buttons and another StackPanel as children. With the help of Margin property the buttons and the child StackPanel are spaced vertically 10 generic pixels apart. The child StackPanel has Horizontal orientation (controlled by the property “Orientation”) and contains 2 buttons spaced horizontally by 10 generic pixels.

    Grid

    Grid allows to split the area it occupies into rows and columns. There can be different number of rows and columns; the rows can have different height and the columns can have different width.
    Here is a code sample for the Grid: gridsamplezip.doc.
    When run, this sample produces the following window:

    Grid Sample

    Grid Sample

    Let us take a look at the XAML:

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

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width=”80″/>

            <ColumnDefinition Width=”80″/>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>

            <RowDefinition Height=”55″/>

            <RowDefinition Height=”55″/>

        </Grid.RowDefinitions>

        <TextBlock

            Grid.Row=”0″

            Grid.Column=”0″

            Text=”Cell (0, 0)”/>       

        <TextBlock

            Grid.Row=”0″

            Grid.Column=”1″

            HorizontalAlignment=”Right”

            Text=”Cell (1, 0)”/>

        <TextBlock

            Grid.Row=”1″

            Grid.Column=”0″

            Text=”Cell (0, 1)”/>

        <TextBlock

            Grid.Row=”1″

            Grid.Column=”1″

            VerticalAlignment=”Bottom”

            Text=”Cell (1, 1)”/>

    </Grid>

    The rows and columns are defined by RowDefinition and ColumnDefinition tags correspondingly. The item can be placed to a certain cell by defining Grid.Row and Grid.Column properties. Within each cell, the item position is controlled by HorizontalAlignment and VerticalAlignment properties. In addition, one can use Margin property to position an element within each cell.

    Conclusion

    In this part of the tutorial, we presented several Silverlight controls and panels, which are the building blocks of business logic applications. Later we are going to use them to create some cooler stuff.

    Silverlight 2.0 In Examples: Part 0. Introduction

    September 23, 2008

    Introducing Introduction

    Although, this tutorial is called “Silverlight 2.0 In Examples”, this introduction will not have many examples. The main purpose of this article is to describe what Silverlight is, where it can be used, its advantages and shortcomings.

    What is Silverlight

    Silverlight is a framework for developing browser based applications. In this sense it is similar to Html and JavaScript. Just like Html and JavaScript, the Silverlight application is downloaded by the client’s machine from the web server after which it runs within the client’s browser.

    There is a difference, however, between Silverlight and Html. In order for Silverlight to work in your browser you need to install the Silverlight framework from Microsoft. Silverlight framework is a small package (around 5Mb) which can be downloaded and installed pretty fast. In that sense Silverlight is closer to Adobe Flash which requires Flash framework installed, or, for that matter, to Java applets, which require Java Virtual Machine.

    Silverlight can run on different platforms within different browsers. It runs on Windows within IE and Firefox. It also runs on Mac under Safari and Firefox. This should cover most of the possible clients. For the full list of platforms, take a look at the Silverlight article on Wiki. Microsoft also promises to expand the list of platforms and browsers.

    Silverlight 1.0 is an old version that will not be discussed here. It only allows programming in JScript language.

    Instead I will be concentrating on Silverlight 2.0 (still in Beta – according to some unconfirmed internet rumors it will be released at the PDC conference at the end of October). In spite of still being in beta, it was used by the major networks for the coverage of 2008 Olympics and Democratic convention.

    Silverlight 2.0 allows creating applications in many different programming languages. Here, however, I’ll be concentrating on creating Silverlight 2.0 applications in C#.

    C# or other programming languages can be used to program the business logic of the Silverlight application. The presentation and static content are usually created in XAML (though it is possible to create the whole application in C#).

    XAML is an XML based language which (very successfully from my point of view) uses XML hierarchical structure to reflect the containment hierarchy of objects (primarily GUI objects). It will be discussed in more detail later.

    Silverlight applications are usually embedded into HTML or ASP pages. They can be initialized by the user clicking on a certain HTML hyperlink or a button.

    Why I Love Silverlight

    1. Using Silverlight, one can achieve clean separation between business objects and the way they are displayed. That means that the underlying business logic of an application does not have to be polluted with the visual presentation details. Instead XAML files contain DataTemplates that know how to present the data provided by the business logic. These DataTemplates are mapped to the underlying business objects with the help of a technique called binding.
    2. Silverlight controls can be developed lookless (without the visual representation). E.g. a button can be simplified to a control that only has “Click” event. The way the actual button looks and behaves when clicked can be provided by the Control Templates and Styles. This again helps to separate the underlying logic from the visual representation. It also allows having multiple ways in which the same controls are shown without changing the underlying logic.
    3. Silverlight has a powerful set of geometric tools that allow creation of various 2-D drawings. It also has a powerful set of geometric transforms which are easy to user and which can be applied to any Silverlight visual objects.
    4. Silverlight has a rich set of built-in controls, even though, at this point some important controls are missing. WrapPanel, ComboBox, TreeView, ContextMenu are just several examples of missing controls. However, there are some publicly available open source implementations of those controls.
    5. Silverlight includes powerful animation functionality.
    6. On a personal note, I came to Silverlight from the the WPF (Windows Presentation Foundation). Silverlight, from the developer’s point of view is almost a subset of WPF. So, WPF developers should not have any problem mastering Silverlight.

    Because of the clean separation between the business logic and the presentation, I think Silverlight will take a much more prominent role in business application development than Adobe Flash.

    Silverlight Resources

    The best on-line silverlight resource is located at siverlight.net. From there you can get to Jesse Liberty blog. Jesse is a renowned author whose latest passion became Silverlight. There are other valuable places on the internet including codeproject.com.

    Finally an Example: “Hello World” Application in Silverlight

    In order to build Silverlight applications you need to have the following packages installed: VS 2008 and Silverlight Tools Beta 2 for Visual Studio 2008.

    To create a Silverlight application, open VS 2008, go to File menu and choose New->Project. On the left side panel choose Visual C#->Silverlight to be the Project Type. Choose “Silverlight Application” on the right hand side. Also choose the path where you want your solution to reside and choose the name of the solution (and the project) to be “HelloWorld”. At the next screen choose “Dynamically generate an HTML test page to host Silverlight within this project” for simplicity.

    In your VS solution window you will see that Visual Studio generated 4 files containing C# and XAML code: App.xaml, App.xaml.cs, Page.xaml, Page.xaml.cs. You do not have to pay much attention to the App.xaml and App.xaml.cs files. They are only used to initialize the Silverlight application. Most times you won’t have to touch them. The really interesting files are Page.xaml and Page.xaml.cs.

    Here is the content of Page.xaml file: 

    <UserControl x:Class=”HelloWorld.Page”

        xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

        xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

        Width=”400″ Height=”300″>

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

     

        </Grid>

    </UserControl>

    Let us investigate its contents line by line.
    UserControl is the superclass from which our Page control is derived.
    HelloWorld.Page is the namespace and the class name of our control.
    Two lines that start with xmlns should be present in almost every XAML file. They declare the default and “x:” namespaces, making available much of Silverlight functionality to be used within the file.
    Width and Height properties specify Width and Height of our Page control.
    Finally Grid is a panel. Panels are controls in charge of positioning other controls.
    To Display “Hello World” within the Silverlight application all we need to do is to add the following line to the Grid:

    <TextBlock Text=”Hello World”/>

    Eventually we never touched Page.xaml.cs file. That is because we did not want our application to have any behavior: all we wanted was to display a static “Hello World” message.
    The code for this example can be found at helloworldzip.doc. This is a simple .zip file. Remove “.doc” extension and change the name of the file to HelloWorld.zip.

    Silverlight Tutorial Project

    September 21, 2008

    I would like to start a Silverlight tutorial in several installments, and, perhaps, crosspost it at several other web sites. I would appreciate if people specify what they want to know about Silverlight in the comments.