Silverlight to Angular – 2 (Data Binding)

One of the main features in Silverlight is binding. There are two ways you do data binding. ‘One way’ or ‘two way’ data binding. There is one more ‘onetime’, I am skipping it on purpose here. Let’s first see what they are and when do you use them and then see its associated implementation in both Silverlight and Angular.JS

One-way: As the name suggests, as the data in data model changes, the changes are reflected in the View. When it is a one way data binding, user is not allowed to change the value in the view. It is meant to be showing the data coming from the model only. The read only controls are the excellent candidates for this kind of binding. This eliminates the overhead of two way binding.

image

Problem: Display number of times a button is clicked using one-way binding.

Silverlight:

View: For our problem, we need three controls.

  1. A text block with text specifying the ‘Number of clicks:’
  2. A text block which displays number of clicks itself.
  3. A button to click to modify the data.
1 <TextBlock Grid.Row="0" Grid.Column="0">Number of Clicks: </TextBlock> 2 <TextBlock Grid.Row="0" Text="{Binding NumberOfClicks, Mode=OneWay}" Grid.Column="1"/> 3 <Button Grid.Column="1" Grid.Row="1" Command="{Binding ClickMe}" CommandParameter="">Click me</Button>

ViewModel: We have a public property called ‘NumberOfClicks’ which is what bound to our text block to show number of times the button clicked. The second one is IActionCommand to trigger click event for the button. Every time button clicked, we increment the counter and raise the property changed event so that view can pick up the modified value.

1 [ExportAsViewModel(typeof(MainPageViewModel))] 2 public class MainPageViewModel:BaseViewModel 3 { 4 public IActionCommand<string> ClickMe { get; private set; } 5 private int _numberOfClicks = 0; 6 public int NumberOfClicks 7 { 8 get { return _numberOfClicks; } 9 set { _numberOfClicks = value; RaisePropertyChanged(()=>NumberOfClicks); } 10 } 11 12 public MainPageViewModel() 13 { 14 ClickMe = new ActionCommand<string>(p=> NumberOfClicks = NumberOfClicks+1); 15 } 16 }

Angular:

In Angular, to achieve one way binding, i.e., $scope -> view, all you do is to use ng-bind directive instead of ng-model. Alternate solution is to use the default {{variable}} notation, which also behaves same way as the ng-bind. I prefer {{variable}} approach. Here is an example which demonstrate one way binding using ng-bind.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="Controller"> 8 Number of Clicks:{{NumberOfClicks}} 9 <button ng-click="onClick()">Click Me</button> 10 </div> 11 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 12 <script src="Scripts/Controller.js"></script> 13 </body> 14 </html>

Line (8) is the one way binding. Even though ng-bind was not specified, it is the default binding. So you do not explicitly specify the ng-bind and I prefer to stay with {{}} approach.

ViewModel/Controller:

1 function Controller($scope) { 2 $scope.NumberOfClicks = 5; 3 $scope.onClick = function() { 4 $scope.NumberOfClicks = $scope.NumberOfClicks + 1; 5 }; 6 }

[Note: When you run the code, if the number is not incrementing then, one possibility is that, you might not have ‘()’ next to the onClick function in the HTML. Been there done that.]

Two-way: This is the standard and most used data binding. In this type of binding, when a data in data model changes, the changes reflected in View. In the same way, user is allowed to change the data in view and the change pushed to Model. In my opinion this is what made Silverlight so awesome and now it carries to Angular.

image

Problem: Get name from user and provide a greeting to the user. Allow user to add ‘!’ to the end of the name using a button.

Silverlight: For our problem we need three controls

View:

  1. A text block which display ‘Enter Name’.
  2. A text box to get user name.
  3. A text block to display ‘Hello {name}’.
  4. A button to add ‘!’ char to the name, which should modify both the (2) and (3) control values.
1 <TextBlock>Name: </TextBlock> 2 <TextBox Grid.Column="1" Text="{Binding Name, Mode=TwoWay}"></TextBox> 3 <Button Command="{Binding ClickMe}" CommandParameter="" Grid.Column="2">Add !</Button> 4 <TextBlock Grid.Row="1" Text="{Binding HelloName}"></TextBlock>

If you notice line (2) the text box binding ‘Name’ is set to ‘TwoWay’, which means, user is allowed to enter data which will change the viewmodel, but if the data changes in the model, it get reflected back on the view as well.  When you run the code, you will notice, when user enters ‘Unni’ in the name and press the button, it not only display ‘Hello Unni!’ in the text block in line (4) but also changes the text box (line 2) to ‘Unni!’. In this example, line (4) is still one way, so when data changes in the model, the change will get reflected in the view.’

ViewModel:

1 [ExportAsViewModel(typeof(MainPageViewModel))] 2 public class MainPageViewModel:BaseViewModel 3 { 4 private string _name; 5 public string Name 6 { 7 get { return _name; } 8 set 9 { 10 _name = value; 11 RaisePropertyChanged(() => Name); 12 } 13 } 14 public IActionCommand<string> ClickMe { get; private set; } 15 16 private string _helloName; 17 18 public string HelloName 19 { 20 get { return _helloName; } 21 set 22 { 23 _helloName = value; 24 RaisePropertyChanged(() => HelloName); 25 } 26 } 27 28 public MainPageViewModel() 29 { 30 ClickMe = new ActionCommand<string>(Clicked); 31 } 32 33 public void Clicked(string obj) 34 { 35 if (!Name.EndsWith("!")) 36 Name += "!"; 37 HelloName = "Hello " + Name; 38 } 39 }

[Note: If you have trouble with the code, make sure, all the properties have RaisePropertyChanged event in it. Also make sure the button click command name matches the command in the view model. The last part make sure all the exports attributes are marked properly]

Angular:

By default, if you do not specify ng- in the element, then one way binding is assumed. It means, whenever you use {{variable}}, it is considered one way binding. Anytime data change happens in the controller, view gets the modified data. $scope -> view. On the other hand if you specify ‘ng-model’ attribute in the element, it is considered two way binding. It means, user changes will be pushed to model and any model changes will be pushed to view. $scope <-> model.

View:

1 <!DOCTYPE html> 2 <html ng-app> 3 <head> 4 <title></title> 5 </head> 6 <body> 7 <div ng-controller="controller"> 8 Name: <input ng-model="Name"/> 9 <button ng-click="onClick()">Click Me</button> 10 <br />{{HelloName}} 11 </div> 12 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script> 13 <script src="scripts/controller.js"></script> 14 </body> 15 </html>

Line (8) is a two way binding to a variable ‘Name’ in the $Scope. It means, when user enters a value in the input, the user entered value get pushed to the $scope variable Name. On the other hand, line (10), when ever there is a value change to ‘HelloName’ variable in $scope, it get pushed to the view.

ViewModel/Controller: (Going forward, I am going to refer this as Controller instead of ViewModel).

1 function controller($scope) { 2 $scope.Name = ""; 3 $scope.HelloName = ""; 4 5 $scope.onClick = function () { 6 debugger; 7 if ($scope.Name[$scope.Name.length - 1] !== "!") 8 $scope.Name = $scope.Name + "!"; 9 $scope.HelloName = 'Hello ' + $scope.Name; 10 }; 11 }

Initially when the HTML is rendered in the browser, both Name and HelloName will have empty string. When the user enters a value, say ‘Unni’ in the input box and click on ‘Click Me’ button, controller executes ‘onClick’ function and sets the Name to ‘Unni!’ (note ‘!’ at the end) and make ‘HelloName’ as ‘Hello Unni!’. So both the variables ‘Name’ and ‘HelloName’ changed in the model so the changes pushed back to view. Now if you notice, your input changed to Unni! Instead of Unni, thus making variable ‘Name’ two way binding. While HelloName pushed to view with new value making it one way binding.

So the bottom line is, if you use ‘ng-model’, it is two way binding otherwise it is one way binding.

Advertisements

Use PromptBox to get simple user input in Silverlight

When we create Silverlight application we will run into a situation where we need to get very simple input from a user apart from traditional ok or cancel. If you are after the simple ok or cancel then message box serve the purpose but if you need to get some kind of data from the user as simple as a number or a string, then we do not need to create popup window or child window in Silverlight if you are using component one controls.

Out of the box, component provides a user control called C1PromptBox which as the name suggests, prompt the user for an input and goes on it merry way without cluttering code with complicated code.

Let’s look at this with simple example;

C1PromptBox.Show(“Enter your age”, “Age prompt”, (s, r) =>
{
If (r ==MessageBoxResult.OK)
{
//age will be in s, parse the age out
}
else
{
// user pressed cancel
}
}

If you expect the last two line to execute after getting user input, then if condition has to be inside the C1PromoptBox.Show bot outside like the code shown

above. The proper way to write the code

In the above example, when the code executes it will prompt the small message box to enter the age and you parse or handle the value on the event user press ok button.

One thing we need to be mindful, the Show event is a delegate so if you have any instructions that need to execute after prompt is successful, it has to be inside the MessageBoxResult.OK condition not outside the show delegate since UI will take control back after show event is successful.

Here is a scenario;

  1. public void PromptAge()
  2. {
  3. int age = 0;
  4. C1PromptBox.Show(… get age);
  5. if (age <= 30)
  6. HandleLessThanThirtyAge();
  7. }
 

In the above example we are expecting the dialog to be shown for user to enter the age. After the user enters the age, line 05 gets control and executes HandlesLessThanThirtyAge method if the age is less than or equal to 30. But that is not how it works. When PromptAge executes, it execute prompt box and while it wait for user to enter something, the UI thread continues and executes 05 through so age will be always 0 and it never executes the method on 06. The reason for that is, the behavior on how to handle ok or cancel is delegate inside the prompt box. So for it work properly. ie, after user enters the ages, get the age and based on the age to execute the HandleLessThanThirtyAge, we need to move the if condition inside the PromptBox delegate itself as shown below

  1. public void PromptAge()
  2. {
  3. C1PromptBox.Show("msg", "prompt", (s, r) =>
  4. {
  5. if (r == MessageBoxResult.OK)
  6. {
  7. //parse age from s
  8. if (age <= 30)
  9. HandleLessThanThirtyAge()
  10. }
  11. };
  12. }
One of the feature missing in this is default value for the prompt, I requested this feature with Component One and it is schedule be part of their feature release. By providing most commonly used value as default value, we could save one key stoke for the user. Once the feature is available I will update this blog.

XAP optimization

I created a very simple example which have two grids, one is master grid and another one is total grid. Total gird, totals any field which has decimal field in it. Nothing complicated. As any developer, I was adding code if I miss any namespace I add them. Some time, I add some system references that I might not even use later as I progress but forget to remove from the solution. So with that all in mind, after building the solution and run as I expected it to run and deploy it. Some time you night get a complain that it takes for ever to load. If you ever hear or if you see that yourself when you start testing, take a look at the size of the XAP file in ClientBin folder. Chances are your XAP is big.

Going back to the sample I was talking about, with out any code changes, the XAP file size is 880KB. Next we are going to see how we can reduce the size of the file and user experience is better. I attempted that with couple of ways.

1. Using Component One XAP optimizer:

I got a license for Component One XAP optimizer and thought of give a world and see how much size reduction happens. I pass the current XAP as the input and it can generate new XAP file or override the existing one. Here is the result of the XAP optimization.

image

The new file size is 336KB, more than 50% size reduction. In this approach the files are still in single XAP file and there are no external files to download. What I attempted was a very simple solution, it seems it has lot more features that you could use for more complex projects.

2. Using Visual Studio XAP optimization using application library caching:

From SL3 and forward,  there is a way we can optimize the XAP files by removing the system and third party controls from the required elements of XAP. You can read more about how it is done in Tim’s blog. Using that approach I was able to get the XAP file size reduced to 229KB. All the required dlls are separated out to its on ZIP files.

image

[Following was incorrect. As of now, following combination broke the Silverlight application. Once I know why it is not working, I will update here.]

3. Using Component One Optimization on top Visual Studio optimization:

As you have guessed, we should be able apply C1 optimization and get a better initial performance. With the optimization applied the XAP file size reduced to 166KB.

I am really happy with the overall size reduction from 880KB to 166KB. If any of you have any other better way of doing optimization, would love to hear it.

Debugging Silverlight application using Fiddler

Debugging RIA services is not always plain and simple. When you start a new application using RIA services if things are not setup properly you have initial hick-up for debugging the code. If you were using Authentication services then the error will be most common error that login failed without giving any other details. There are lot of blogs out there specifying how to debug this situation, but what I want to mention in this blog is that, use Fiddler when possible to see what is going between the wire.  It works just fine when your web site is hosted and you are monitoring the request and responses from client side.

When it comes to debugging the localhost environment only thing you need to remember is to start the web site as http://localhost./website (emphasis on the ‘.’ at the end of the local host). because of the limitation in fiddler, If you run the normal localhost, it will not monitor. So make sure you use ‘localhost.’ with that you should able to see all the traffic going between client and server.

This link has alternate way of doing it as well.  If you do not want to add ‘.’ at the end of the localhost or the solution in the fiddler web site, then other option is to modify the hosts files (%WINDIR%\System32\drivers\etc\hosts) and then add the following like

127.0.0.1 name

With that change if you would access the web site or the app, instead of calling http://localhost now you can call http://name, fiddler will capture the traffic.

Technorati Tags: ,

Can you see now – Bing maps

This will be a short post.

Nowadays if we want to find a location or driving direction we use internet maps. I am always fascinated by the complexity of the maps. Even though they are just two co-ordinates, Altitude and latitude.   I have seen application which has integrated maps in it. recently I came across a blog which took me to bing map sdk. I was thrilled to see the SDK to use Bing map inside. Anyone who ever wanted to learn how to integrate map inside the application, that is your solution.

Lately all experiments I am doing, is done in Silverlight, it is way to educate myself on Silverlight. So I started binging to see if there is a way I can use the maps in Silverlight and here it is. To my surprise with in 30 minutes I was able to get everything running and have my first program showing maps.

Technorati Tags: ,

Obey the commands in Jounce (3)

One of my favorite thing in Silverlight is command. It makes the code look very simple and elegant. This is build on top of part 2 of the blog. As always, lets first look at the result.

The default initial screen

This is same as previous now. Now if you type the name differently and focus out (do not click on ‘Say Hello’) You will get the following screen

Now click on the ‘Say Hello’ button which will render the following screen.

You see that, when I click on say hello, the word command get added to the name text block and in the bottom label as well. What I want to do demonstrate here is that, it is very easy to do commanding. Lets look at the code. In this one, my view XAML changed a bit (MainPage.XAML) as follows

<Grid x:Name=”LayoutRoot” Background=”White”>
<sdk:Label Height=”28″ HorizontalAlignment=”Left” Margin=”38,32,0,0″ Name=”label1″ VerticalAlignment=”Top” Width=”47″ Content=”Name:” />
<TextBox Height=”23″ HorizontalAlignment=”Left” Margin=”81,28,0,0″ Name=”textBox1″ VerticalAlignment=”Top” Width=”235″ Text=”{Binding Name, Mode=TwoWay}” />
<sdk:Label Height=”28″ HorizontalAlignment=”Left” Margin=”43,125,0,0″ Name=”label2″ VerticalAlignment=”Top” Width=”273″ Content=”{Binding HelloName}” />
<Button Content=”Say Hello” Height=”23″ HorizontalAlignment=”Left” Margin=”43,77,0,0″ Name=”button1″ VerticalAlignment=”Top” Width=”263″ Command=”{Binding SayHelloCommand}” CommandParameter=”{Binding ElementName=textBox1, Path=Text}”/>
    </Grid>

Nothing changed except the Button control. Now I have two additional attributes added. They are Command and CommandParameter. The Command in here says what command to execute when user click the button. The command parameter says what is the parameter for command. For command parameter, I am reading the Name text block and passing the text. Now lets look at the command implementation, it is implemented in the view model as follows

namespace simplelabel
{
using Jounce.Core.ViewModel;
using Jounce.Core.View;
using System.ComponentModel.Composition;
using Jounce.Core.Command;
using Jounce.Framework.Command;

[ExportAsViewModel(“Shell”)]
public class MainPageViewModel:BaseViewModel
{
private string _name;
public string Name
{
get
{
if (_name == null)
_name = “Unni”;
return _name;
}
set
{
_name = value;
RaisePropertyChanged<string>(() => Name);
RaisePropertyChanged<string>(() => HelloName);
}
}

public string HelloName
{
get
{
return “Hello ” + Name;
}
}

public IActionCommand<string> SayHelloCommand { get; private set; }

        public MainPageViewModel()
{
SayHelloCommand = new ActionCommand<string>(name => Name = name + ” Command”);
}
    }
}

We declared new command called ‘SayHelloCommand’ of type IActionCommand and it gets instantiated at the view model constructor with delegate on what is it supposed to do. In the delegate what we are doing is setting the Name value with current value in the text block and then add text ‘Command’ to distinguish between the command execution and focusing out of the text block. Since we are setting the Name field, both the text block and the bottom label, which are bound field take the new values.

That is it.

Technorati Tags: ,,

Simple Binding in Jounce (2)

Building on what we have developed in my previous post, in this example we will display the name it is entered in the text block in another field. The final result would like the following

When the application starts the initial screen would like this

When the user change value in the Name field and hit ‘Say Hello’ and it will then put the new value in the bottom part like the following

This is to demonstrate the two way binding and making the second label aware of the changes.

 

The main page xaml will have the code like the following to add one button for ‘Say Hello’ and the second one to display the new text ‘Hello ‘ + name.

<Grid x:Name="LayoutRoot" Background="White">
       <sdk:Label Height="28" HorizontalAlignment="Left" Margin="38,32,0,0" Name="label1" VerticalAlignment="Top" Width="47" Content="Name:" />
       <TextBox Height="23" HorizontalAlignment="Left" Margin="81,28,0,0" Name="textBox1" VerticalAlignment="Top" Width="235" Text="{Binding Name, Mode=TwoWay}" />
       <sdk:Label Height="28" HorizontalAlignment="Left" Margin="43,125,0,0" Name="label2" VerticalAlignment="Top" Width="273" Content="{Binding HelloName}" />
       <Button Content="Say Hello" Height="23" HorizontalAlignment="Left" Margin="43,77,0,0" Name="button1" VerticalAlignment="Top" Width="263" />
   </Grid>

The next change is in the viewmodel.

namespace simplelabel
{
    using Jounce.Core.ViewModel;
    using Jounce.Core.View;
    using System.ComponentModel.Composition;

    [ExportAsViewModel("Shell")]
    public class MainPageViewModel:BaseViewModel
    {
        private string _name;
        public string Name
        {
            get
            {
                if (_name == null)
                    _name = "Unni";
                return _name;
            }
            set
            {
                _name = value;
                RaisePropertyChanged<string>(() => Name);
                RaisePropertyChanged<string>(() => HelloName);
            }
        }

        public string HelloName
        {
            get
            {
                return "Hello " + Name;
            }
        }
    }
}

The changes are, I have added the HelloName public variable, which is bound in the main view XAML.  One other new line is in the setter of ‘Name’, where I raise the property changed event for ‘HelloName’ when the Name field changes.

Normally when we raise property event change, we end up using constant values and then check the constant values in the places where it is used, those complexities are removed from developer perspective in Jounce which I really like.

That is it.

Technorati Tags: ,,