Sunday, April 14, 2013

Silverlight 5.0

 

When you compile you SL application number of actions are undertaken.

- Your code is verified to be correct.

- Silverlight App is compiled into a DLL. It is the DLL used by silverlight at run time.

These days MSBuild by Microsoft is used to step up the build process. It uses XML model scripts to determine what happens. These scripts contain ordered set of instructions. There are hundreds of predefined tasks. And also you can create your own ones

Actually a visual studio project file (csproj) is really a build script file. It is well formed XML containing build instructions. When you build you application is visual studio it calls MSBuild. MsBuild reads the build instructions and performs the requested build steps. Eventually MSBuild calls the compiler (vbc.exe, csc.exe). The language compiler then compiles the code into executable.

Assemblies

SL apps runs on the client.

A silverlight assembly must be downloaded to the client.

Any assembly you use must be compiled sepcifically for silverlight use.Your company libs, third party .

image

Core assemblies are :

  1. mscorlib.dll
  2. system.dll
  3. system.core.dll
  4. System.Net.dll
  5. System.Windows.dll
  6. System.Windows.Browser.dll
  7. System.xml.dll

Silverlight Add-on Assemblies:

  1. System.Windows.Controls.dll – Tree view, Tab control, date picker, calendar and Grid splitter controls
  2. System.Windows.Controls.Data.dll – DataGrid, DataPager
  3. System.Windows.Controls.Data.Input.dll – Data bound forms, Label, Description viewer, Validation summary
  4. System.Windows.Controls.Input.dll – AutoCompleteTextbox
  5. System.Windows.Controls.Navigation.dll – Frame and Page controls basis of silverlight navigation system.

image

XAML is used to write the code (layout) for silverlight. XAML is used for :

  • Silverlight
  • Windows Phone
  • Windows 8 Metro
  • XPS – XML Paper Specification

XAML is really an XML.
XAML doc is limited to single root element and that root is typically a UserControl element.
Normal XML rules apply to XAML:
    Attributes values must be delimited (“”, ‘ ‘ )
    User proper tag closure (<user></user> or <user />)


XAML elements are mapped to equivalent .NET classes. For example <Button> is an object element in XAML. So using an object element in XAML is same as :

  1. Instantiating an instance of the Button class
  2. Calling the default parameterless constructor.

Attributes:

XAML types has several types of attributes:

  1. Property Attributes: These correspond to object property. For example Width, Height
  2. Event Attributes: These correspond to object events. For example MouseMove
  3. Directive Attributes: These are parser instructions that have no programmatic equivalent. For ex: Assigning a localization ID with x:Uid, x:Name
  4. Attached Property Attributes: For example Grid.RowSpan

XAML Namespaces:

To put groups of elements, it is common to use Namespaces. In XAML using xmlns attrubute we can put elements into a namespace.

Type Converters
These are just like data type casting in .NET.

Markup Extensions

if you need runtime calculation and want that value to be assigned to a property in XAML, then you must use Markup Extensions.

The syntax for markup extension is like :image

Categories of markup Extensions:

  • DataBinding : Get datasource value and assign it to a property.
  • TemplateBinding: get value from a control template and assign to property.
  • StaticResource: Lookup resource defined in ResourceDictionary.
  • Null: Assign null value to a property.
  • Custom: We can create our own markup extension implementing IMarkupExtension interface.

Dependency Properties System:

SL uses a unique property system called Dependency property system. This was invested by WPF team of Microsoft. This new system enhances the underlying .NET framework and promise elements to plugin to useful services like animations, databinding, tempaltes, styles.

Dependency system contains two important parts:
1. Dependency Property
2. Attached Property

image

Creating a dependency property 

Creating a dependency property isn’t difficult, but the syntax takes a little getting used to. It’s
thoroughly different from creating an ordinary .NET property.
The first step is to define an object that represents your property. This is an instance of the
DependencyProperty class (which is found in the System.Windows namespace). The information about your property needs to be available all the time. For that reason, your DependencyProperty object must be defined as a static field in the associated class.
For example, consider the FrameworkElement class from which all Silverlight elements inherit.
FrameworkElement defines a Margin dependency property that all elements share. It’s defined like this:
public class FrameworkElement: UIElement
{
public static readonly DependencyProperty MarginProperty;
...
}

By convention, the field that defines a dependency property has the name of the ordinary property
plus the word Property at the end. That way, you can separate the dependency property definition from the name of the actual property. The field is defined with the readonly keyword, which means it can be set only in the static constructor for the FrameworkElement.

Registering Dependency Property:

Defining the DependencyProperty object is just the first step. For it to become usable, you need to
register your dependency property with Silverlight. This step needs to be completed before any code
uses the property, so it must be performed in a static constructor for the associated class.
Silverlight ensures that DependencyProperty objects can’t be instantiated directly, because the
DependencyProperty class has no public constructor. Instead, a DependencyProperty instance can be
created only using the static DependencyProperty.Register() method. Silverlight also ensures that
DependencyProperty objects can’t be changed after they’re created, because all DependencyProperty
members are read-only. Instead, their values must be supplied as arguments to the Register() method.
The following code shows an example of how a DependencyProperty can be created. Here, the
FrameworkElement class uses a static constructor to initialize the MarginProperty:
static FrameworkElement()
{
MarginProperty = DependencyProperty.Register("Margin",
typeof(Thickness), typeof(FrameworkElement), null);
...
}

image

The DependencyProperty.Register() method accepts the following arguments:
• The property name (Margin in this example).
• The data type used by the property (the Thickness structure in this example).
• The type that owns this property (the FrameworkElement class in this example).
• A PropertyMetadata object that provides additional information. Currently,
Silverlight uses the PropertyMetadata to store just optional pieces of information:
a default value for the property and a callback that will be triggered when the
property is changed. If you don’t need to use either feature, supply a null value, as
in this example.

Attached Property:
An attached property is a full-fledged dependency property, and like all dependency properties, it’s managed by the Silverlight property system. The difference is that an attached property applies to a class other than the one where it’s defined.
The most common example of attached properties is found in the layout containers. For example, the Grid class defines the attached properties Row and Column, which you set on the contained elements to indicate where they should be positioned. Similarly, the Canvas defines the attached properties Left and Top that let you place elements using absolute coordinates.
To define an attached property, you use the DependencyProperty.RegisterAttached() method instead of Register(). Here’s the code from the Grid class that registers the attached Grid.Row property:

RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), null);

Silverlight Panels:

  • Stack Panel
  • Grid
  • Canvas
  • VirtualizingStackPanel (used by List Controls)
  • Wrap Panel
  • Dock Panel

Tip: To jump quickly from XAML to Event handling code, right click the event in xaml and choose Navigate to Event Handler option.

Assembly caching:

By default it is turned off and it can be turned on from Visual Studio project properties.

image 

Silverlight Object Parameters:

Source (required) - A URI that points to XAP file.
onError: A js event handler triggered when unhandled exception occurs.
background
minRuntimeVersion: min version of SL that client must have
autoUpgrade: default is True.
enableHTMLAccess: To access HTML elements within SL code
initParams: string to pass custom initialization information.
splashScreenSource:
windowless: just like transparent
onSourceDownloadProgressChanged:
onSourceDownloadComplete:
onLoad:
onResize'

Binding:

One way Binding:

Element-to-Element Binding
One-Way Binding
To understand how you can bind an element to another element, consider the simple window shown in Figure.
image
It contains two controls: a Slider and a TextBlock with a single line of text. If you pull the thumb in the slider to the right, the font size of the text is increased immediately. If you pull it to the left, the font size is reduced.

Clearly, it wouldn’t be difficult to create this behavior using code. You would simply react to the
Slider.ValueChanged event and copy the current value from the slider to the TextBlock. However, data binding makes it even easier. When using data binding, you don’t need to make any change to your source object (which is the Slider in this example). Just configure it to take the right range of values, as you would ordinarily.
<Slider x:Name="sliderFontSize" Margin="3" Minimum="1" Maximum="40" Value="10">
</Slider>

The binding is defined in the TextBlock element. Instead of setting the FontSize using a literal value, you use a binding expression, as shown here:
<TextBlock Margin="10" Text="Simple Text" x:Name="lblSampleText" FontSize="{Binding ElementName=sliderFontSize, Path=Value}" >
</TextBlock>

Data binding expressions use a XAML markup extension (and hence have curly braces). You begin with the word Binding, followed by any constructor arguments (there are none in this example) and then a list of the properties you want to set by name—in this case, ElementName and Path. ElementName indicates the source element. Path indicates the property in the source element. Thus, this binding expression copies the value from the Slider.Value property to the TextBlock.FontSize property.

Tip: The Path can point to a property of a property (for example, FontFamily.Source) or an indexer used by a property (for example, Content.Children[0]). You can also refer to an attached property (a property that’s defined in another class but applied to the bound element) by wrapping the property name in parentheses. For example, if you’re binding to an element that’s placed in a Grid, the path (Grid.Row) retrieves the row number where you’ve placed it.

One of the neat features of data binding is that your target is updated automatically, no matter how
the source is modified. In this example, the source can be modified in only one way—by the user’s
interaction with the slider thumb. However, consider a slightly revamped version of this example that adds a few buttons, each of which applies a preset value to the slider. Click one of these buttons, and this code runs:
private void cmd_SetLarge(object sender, RoutedEventArgs e)
{
   sliderFontSize.Value = 30;
}
This code sets the value of the slider, which in turn forces a change to the font size of the text
through data binding. It’s the same as if you had moved the slider thumb yourself.
However, this code wouldn’t work as well:
private void cmd_SetLarge(object sender, RoutedEventArgs e)
{
lblSampleText.FontSize = 30;
}
It sets the font of the text box directly. As a result, the slider position isn’t updated to match. Even
worse, this has the effect of wiping out your font size binding and replacing it with a literal value. If you move the slider thumb now, the text block won’t change at all.

Two way Binding:

Interestingly, there’s a way to force values to flow in both directions: from the source to the target and from the target to the source. The trick is to set the Mode property of the Binding. Here’s a revised bidirectional binding that allows you to apply changes to either the source or the target and have the other piece of the equation update itself automatically:

<TextBlock Margin="10" Text="Simple Text" Name="lblSampleText"
FontSize="{Binding ElementName=sliderFontSize, Path=Value, Mode=TwoWay}" >
</TextBlock>

In this example, there’s no reason to use a two-way binding, because you can solve the problem by manipulating the value of the slider rather than changing the font size of the TextBlock. However, consider a variation of this example that includes a text box where the user can set the font size precisely.

image

Here, the text box needs to use a two-way binding, because it both receives the bound data value
and sets it. When the user drags the slider (or clicks a button), the text box receives the new slider value.And when the user types a new value in the text box, the binding copies the value to the slider.Here’s the two-way binding expression you need:
<TextBox Text="{Binding ElementName=lblSampleText, Path=FontSize, Mode=TwoWay}">
</TextBox>

TIP: If you experiment with this example, you’ll discover that the text box applies its value to the slider only once it loses focus. This is the default update behavior in Silverlight, but you can change it by forcing immediate updates as the user types.

When setting margins, you can set a single width for all sides, like this:
<Button Margin="5" Content="Button 3"></Button>
Alternatively, you can set different margins for each side of a control in the order left, top, right,
bottom:
<Button Margin="5,10,5,10" Content="Button 3"></Button>
In code, you can set margins using the Thickness structure:
cmd.Margin = new Thickness(5);

TIP: If you want to divide the remaining space unequally, you can assign a weight, which you must place before the asterisk. For example, if you have two proportionately sized rows and you want the first to be half as high as the second, you could share the remaining space like this:
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
This tells the Grid that the height of the second row should be twice the height of the first row. You
can use whatever numbers you like to portion out the extra space.

Tip: Remember, if a Grid has just a single row or column, you can leave out the RowDefinitions section. Also, elements that don’t have their row position explicitly set are assumed to have a Grid.Row value of 0 and are placed in the first row. The same holds true for elements that don’t supply a Grid.Column value.

An event handler that responds to a button press by switching into full-screen mode:
private void Button_Click(object sender, RoutedEventArgs e)
{
   Application.Current.Host.Content.IsFullScreen = true;
}

No comments: