Posts Tagged ‘Introduction’
Getting started with Meteor
This post is an introduction to Meteor and intended to developers who are new to Meteor.
So what is Meteor?
Meteor is an ultra-simple environment for building modern websites. What once took weeks, even with the best tools, now takes hours with Meteor.
Yes Meteor is a java script web framework that can do wonders with less line of code. Watch this Screen cast before you proceed. One of the feature that I really liked is the real time pushing of changed data set to all the connected clients in real time, without any complex code from developers.
Installing Meteor
I use Windows as my development environment, so we need to use the Meteor msi installer. We can get the latest installer from http://win.meteor.com/. Download the setup and install it. After installation we need to start CMD / Bash as administrator or reboot for it to catch the environment changes.
Developing Meteor App
Open the command prompt and change directory to your desired folder, say f:\sony\tracers\meteor. Then issue the create command as shown below.
>meteor create helloworld
Here ‘helloworld’ is my application name. You can give any name for your application. The command creates a folder with the application name with a .meteor folder and sample html and js file. To check whether the application created correctly, type ‘meteor’ in the command prompt as shown below.
As you can see our application is running in localhost, we can fire any browser to that url and can see your first meteor app running. I am leaving the screen shot, see it your self.
Explore Meteor in Detail
It’s time to see some of the cool features of Meteor. I created a small application called pointofsale. Rest of the post will be around this application. It’s a small application I started in Meteor with below functionality.
-
Product Entry
-
Order entry
I completed only Product Entry and Listing.
Disclaimer: I am very bad in Web UI development, so you will see a very ugly UI
Folder Structure
You can find more details about file structuring here. My app’s folder structure is shown below
I use meteor Knockout as my MVVM framework.
Templates
Templates are like User controls in ASP.NET. That has set of controls and logic. Meteor has a nice documentation about Templates, check it out before you move on.
Let’s see the Product Entry Template to get some insight.
<template name="productEntry"> <table> <tr> <td><Label >Product Code</Label></td> <td><label>Product Name</label></td> </tr> <tr> <td><input type="text" id="prodCode" data-bind="value: productCode" placeholder="Code"/></td> <td><input type="text" id="prodName" data-bind="value: productName" placeholder="Name"/></td> <td><input type="button" value="Add" id="addProduct"/></td> </tr> </table> <br> </template>
As I said I use knockout js, so for data binding I added knock out attribute data-bind=”value: productCode” to input text.
Let’s see the java script of Product Entry.
if(Meteor.is_client) { var productCode= ko.observable(); var productName= ko.observable(); var viewModel={ productCode:productCode, productName:productName }; Meteor.startup( function() {ko.applyBindings(viewModel); }); Template.productEntry.events={ "click #addProduct": function(){ var id=Products.insert({prodCode:this.productCode(), prodName:this.productName()}); } }; }
Meteor.is_client will return true if the code is running in client, based on this condition we can add client specific codes. As you can see, some of the code above are knockout specific and am not going in detail, except the event handling. You can learn knockout from http://learn.knockoutjs.com/.
Template.productEntry.events={ "click #addProduct": function(){ var id=Products.insert({prodCode:this.productCode(), prodName:this.productName()}); } };
The above code means, capture all the events in productEntry template. Right now productEntry template has only one button named addProduct and we need to handle the click event. That’s what we are doing in the above code. Leave the Products.Insert now, will come back to that later. So how do we handle a click event of another button, it’s very simple as shown below, just separate two functions with a comma.
Template.productEntry.events={ "click #addProduct": function(){ var id=Products.insert({prodCode:this.productCode(), prodName:this.productName()}); }, "click #showAlert": function(){ alert ("Hellow world"); } };
Meteor Collection
In the above code we are referring an object called Products, what is it? It’s a Meteor collection, meteor uses collection to handle data storage and manipulations. Where is it declared? as this Products collection may require in Server side as well. So I created a file in the root called dbRef.js and declared the collection there as shown below.
Products = new Meteor.Collection("product");
We can use this Products collection to add, remove or search products to display in the client. Have a look at the product listing template to see how to use Products collection to display as list.
<template name="productListing"> <label>Product Listing</label> {{#each products}} {{>product}} {{/each}} </template> <template name="product"> <div class="product {{selected}}"> <span class="code">{{prodCode}}</span> <span class="name">{{prodName}}</span> <span><input type="button" value="Delete" id="delete"></input> </span> </div> </template>
Below is the js file of the template.
if(Meteor.is_client) { Template.productListing.products=function (){ return Products.find(); }; Template.product.events ={ 'click': function(){ Session.set("selected_product", this._id); }, "click #delete": function(){ Products.remove({_id:Session.get("selected_product")}); } }; Template.product.selected = function () { return Session.equals("selected_product", this._id) ? "selected" : ''; }; }
The highlighted ‘products’ function uses the Products collection to return all the products entered. Rest of the code is for deleting and selecting the item in the list.
I think I covered the basics of Meteor, will cover more in coming days. You all can download the source code of pointOfSale from Google Drive
Introduction to Caliburn Micro – Part 2
If you haven’t used Caliburn Micro please go through Caliburn Micro Introduction 1
Introduction
Most of the us know what is MVVM model but most of us hesitant to use it in their development. Reason they say is, implementing MVVM in a small project is an overkill. Might be true if they use some complicated MVVM frameworks. In my opinion using Caliburn Micro as a MVVM framework wont overkill or complicate your development rather It will ease our development. Caliburn Micro uses Convention over Configurations, so zero configuration. Last couple of months I did so many tracers and some large projects in Silverlight and WPF using Caliburn Micro, some tracers are just one page projects still I used Caliburn Micro because it’s very easy to develop compare to the normal code behind approach. Some of us are not using Caliburn Micro, the reason is they are doubtful whether it can used in big production level projects as it’s a micro. My answer is yes, I used Caliburn Micro in very complex applications that have more than thirty pages and very complicated functionalities. Don’t underestimate Caliburn Micro by its name, it’s very powerful and easy to learn. I am sure once you start using Caliburn Micro you will never go back to normal codebehind approach in Silverlight or WPF or WP7 neither a different MVVM framework.
iTraveller Development Days
In the development phase of iTraveller I come across lot of blockers related to MVVM model development using Caliburn Micro. In this post I am going to give a brief description about some of my blockers and how I overcome those.
Capturing PreviewDrop/KeyUp or any kind of event in Viewmodel
If you had a chance to look at iTraveller then you can see most of the functionality is based on drag and drop features. My first concern was how to capture drop event or Mouse Down Even or KeyUp Event using Caliburn Micro. What we should do to capture the event is as follows.
<ListBox Name="MyPhotoSets" VerticalAlignment="Stretch"
Visibility="{Binding IsListVisible}" AllowDrop="True" MinHeight="100" MinWidth="100" Style="{DynamicResource PhotoListStyle}" ItemTemplate="{DynamicResource SetTemplate}" ItemContainerStyle="{DynamicResource PhotoListItem}" > <i:Interaction.Triggers> <i:EventTrigger EventName="PreviewDrop"> <cal:ActionMessage MethodName="NewPhotosDropped"> <cal:Parameter Value="$eventArgs"></cal:Parameter> </cal:ActionMessage> </i:EventTrigger> <i:EventTrigger EventName="SelectionChanged"> <cal:ActionMessage MethodName="CategorySelectionChanged"> <cal:Parameter Value="{Binding ElementName=MyPhotoSets,
Path=SelectedItem}"></cal:Parameter> </cal:ActionMessage> </i:EventTrigger> <i:EventTrigger EventName="KeyUp"> <cal:ActionMessage MethodName="KeyUpHappened"> <cal:Parameter Value="$eventArgs"></cal:Parameter> </cal:ActionMessage> </i:EventTrigger> </i:Interaction.Triggers> </ListBox>
You should add a xmlns reference to System.Windows.Interactivity and Caliburn Micro in your xaml page as shown below
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" xmlns:i="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
As you can see in the ListBox I added an event trigger for PreviewDrop and KeyUp. Obviously in you Viewmodel you need to get the DragEventArgs or KeyEventArgs to perform the desired action. We can instruct Caliburn Micro to send these eventargs to the viewmodel function by adding a parameter with value ‘$eventArgs’. Just examine the xaml code.
<i:EventTrigger EventName="PreviewDrop"> <cal:ActionMessage MethodName="NewPhotosDropped"> <cal:Parameter Value="$eventArgs"></cal:Parameter> </cal:ActionMessage> </i:EventTrigger>
In the above code will work like this. If a PreviewDrop event happened in Listbox then call NewPhotosDropped function in my Viewmodel with parameter DragEventArgs. Have a look at my Viewmodel’s NewPhotosDropped function
public void NewPhotosDropped(DragEventArgs e) { //perform your task with parameter e.
}
That’s it now you will get the DragEventArgs in your Viewmodel and do what ever you wanted to do with it.
How to get a View in ViewModel
Most of the case you don’t need a reference to the View. But if in any case you need the reference of your View in your Viewmodel, no issues. You can override OnViewLoaded function of Caliburn micro in Viewmodel and get your view as follows.
protected override void OnViewLoaded(object view) { base.OnViewLoaded(view); MyView myView = view as MyView; if (myView != null) _webBrowserControl = myView.WebBrowserControl; }
How to Bind a ViewModels to a ListBox/ItemsControls that has Custom Template
In some scenarios you may need to bind a list of Viewmodels to a Listbox. If there is no custom templates then no issues. But if the Listbox has some custom templates and the view should show in a contentcontrol placed in the template. Then we should add one dependency property to the content control. Let’s take an e.g
<ListBox x:Name="IndividualComments" BorderThickness="0"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Vertical" Background="Gray"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <Border BorderBrush="Black" BorderThickness="1" CornerRadius="0" Background="Transparent" Margin="1"> <ContentControl ca:View.Model="{Binding}" Margin="0" Background="Transparent"/> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
View model code
private ObservableCollection<IndividualCommentViewModel> _individualComments; public ObservableCollection<IndividualCommentViewModel> IndividualComments { get { return _individualComments; } set { _individualComments = value; } }
In the viewmodel I will have a list of IndividualCommentViewModel. The Listbox in xaml page has some custom template to add a border around the comments. The viewmodel should be binded to a ContentControl inside the border. I tried lot of ways to show my view in the content control but failed. After some search in Caliburn Micro code and googling I came across View.Model dependency property.
As you can see the contentcontrol
<ContentControl ca:View.Model=”{Binding}” Margin=”0″ Background=”Transparent”/>
If we set ca:View.Model=”{Binding}” then Caliburn Micro is intelligent enough to set the View to the content control. ‘ca’ is my xmlns name reference in the page, it can be any name.
Showing Views in Tabcontrols just like in Visual Studio
In iTraveller views like Preview, Search Result, Upload basket, etc are in tabbed view. In one of Rob’s post he explained in detail how we can achieve tabbed view. I just used the same approach he mentioned. I don’t think I need to explain it again.
How to Give a Title to Popup window
After the release, when I recheck iTraveller, I could see that the popup window is showing without the Title I had given in the xaml page. The title is coming with fully functional name of the popup’s viewmodel. So how to solve it. What we need to do is inherit the viewmodel from screen. See the below code to set the title
FlickrAuthorizeViewModel flickrAuthorizeViewModel = new FlickrAuthorizeViewModel(flickrService); flickrAuthorizeViewModel.DisplayName = "Flickr Authorization"; WindowManager winManager = new WindowManager(); winManager.ShowDialog(flickrAuthorizeViewModel, null);
Screen class has a property called Display Name, just set the title to Display Name property as shown above. We are done, the WindowManager will now show the popup with the Title I given in DisplayName property
Event Aggregator
Event Aggregator in Caliburn Micro is a powerful implementation of Observer/Subscriber pattern. The usage of Event aggregator is not limited to ViewModel communication. It can be used in any layer, if there is a need of Observer/Subscriber communication. In iTraveller the messaging (Event Aggregation) is a separate Layer. One main reason I separated it from UI layer is, I may need to raise messages from other layers other than UI. In iTraveller’s User Comment service uses Event Aggregator to publish the result once it’s processed all the comments fetched from Flickr or Facebook. I used Event Aggregator here because once the comments are saved the application does two things, 1: it’s start indexing those comments for searching, 2: a tab need to open to display the comments fetched from Flickr/Facebook. Rather than calling those functionalities the Comment service just publish the processed comments. Who ever listening those messages will get notified, here in iTraveller Indexing service and UserCommentUpdateViewModel is listening to UserComment message. They know what they should do when they got UserComment update notification.
As the day passes… more and more in love with Caliburn Micro . Thanks for reading. Any questions or comments pls update it in the comment section.
An Introduction to Caliburn Micro
Introduction
This post gives some brief introduction to develop Silverlight applications using Caliburn Micro which gives the basic features are:
- BootStrapping
- Conventions to write ViewModels
- Event Aggregation
- Action Message
Once you got the above basic ideas, it’s very easy to develop scalable applications in Silverlight. You can download the latest Caliburn Micro source from CodePlex.
When MVVM pattern introduced into my Silverlight development, initially it’s not digesting for me. But after I got the clear picture of MVVM pattern, I felt It’s very easy to develop Silverlight application that can adaptable to changes very easily. We choose Caliburn Micro as our MVVM framework, one reason it’s very light weight, another reason is the code base is very less. As the code base is very less we can go through it understand it better.
I hope every one who reads this post has some idea of MVVM pattern. In short MVVM separates View (presentation) and the code manipulates the view separately, and called it as View Model. One of the main advantage of MVVM is we can modify View or ViewModel without affecting each other. There is no event handlers for any control in the code behind, so it’s easy to replace one control with another. We can even reuse the same view model for different platform, let say we are developing an app for both Silverlight and WP7, here only difference in view is it’s base classes but UI is same. So we can share the same View Model thus by increase the maintainability and decrease the effort.
How the View and View Model’s will communicate? here the MVVM framework like Caliburn Micro will comes into picture. The MVVM Framework will bind the View and View Model’s. There are several MVVM frameworks in the market like Prism, MVVM Light, etc. but am not going to cover those.
Caliburn Micro uses conventions to bind View and View Model’s, I feel the conventions are better than wiring through code or attributes. You will get the conventions of Caliburn Micro as we progress through this post.
There are two approach in MVVM model, Code first and View first. Which one is better? I am not the person to comment on, their is an age old debate is going on. Personally I prefer Code First approach. But here to simplify things I will do it in View First approach.
Caliburn Micro In Action
Let’s do some small application in Silverlight using Caliburn Micro. The functionality of this app is pretty simple, display a list of customer and allow the user to edit it.
I am going to create a user control to display the details of individual customer. In the listing page we will bind this User control to a List. Let’s create the control.
IndividualResultView.xaml
<Grid x:Name="LayoutRoot" Background="White"> <Border BorderThickness="3" BorderBrush="Black" Margin="3"> <Grid Margin="5"> <Grid.RowDefinitions> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="60"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="120"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock x:Name="lblName" Text="Name" Grid.Row="0" Grid.Column="0"></TextBlock> <TextBlock x:Name="Name" Grid.Row="0" Grid.Column="1"></TextBlock> <TextBlock x:Name="lblAddress" Text="Address" Grid.Row="1" Grid.Column="0" ></TextBlock> <TextBlock x:Name="Address" Grid.Row="1" Grid.Column="1"></TextBlock> <TextBlock x:Name="lblPhoneNumber" Text="Phone#" Grid.Row="2" Grid.Column="0"></TextBlock> <TextBlock x:Name="PhoneNumber" Grid.Row="2" Grid.Column="1"></TextBlock> <HyperlinkButton x:Name="EditCustomer" Grid.Row="3" Content="Edit"></HyperlinkButton> </Grid> </Border> </Grid>
IndividualResultView.xaml.cs
Let’s see the IndividualResultView.xaml.cs, as per the MVVM pattern it should not contain any View related code, other than initializing the UI controls. You can see that our code behind is clean.
using System.Windows.Controls; namespace WCFEnabledSilverlightApp.Views { public partial class IndividualResultView : UserControl { public IndividualResultView() { InitializeComponent(); } } }
We need to create a ViewModel for the above view, let’s do it. I named my ViewModel as IndividualResultViewModel.cs. Below is the code
using DataModel; using Caliburn.Micro; namespace WCFEnabledSilverlightApp.ViewModels { public class IndividualResultViewModel:PropertyChangedBase { string _name; public string Name { get { return _name; } private set { _name = value; NotifyOfPropertyChange(() => Name); } } string _address; public string Address { get { return _address; } private set { _address = value; NotifyOfPropertyChange(() => Address); } } public string PhoneNumber { get; private set; } private Customer _customer = null; public IndividualResultViewModel(Customer customer) { this._customer = customer; this.Name = customer.CustomerName; this.Address = customer.Address; this.PhoneNumber = customer.PhoneNumber; } public void EditCustomer() { EditCustomerViewModel editCustomer = new EditCustomerViewModel(_customer); Screen scrn = new Screen(); WindowManager winMngr = new WindowManager(); winMngr.ShowDialog(editCustomer); } } }
Convention 1
We learned our first convention of Caliburn Micro. The UI should suffix with “View”. The View Model should suffix with “ViewModel” and prefix with ViewName
<ViewName>View.xaml
<ViewName>ViewModel.cs
Eg.
IndividualResultView.xaml
IndividualResultViewModel.cs
Convention 2
You might have noticed that in the view and viewmodel we used some convention. The name of TextBlock that display the customer details have a corresponding property in ViewModel. For E.g. the TextBlock name for displaying Customer Name is “Name” and in ViewModel you can see a property “Name”. The Caliburn Micro will bind the Property in the ViewModel to the View. That means what ever value we set for property “Name” will be displayed in the View. Pretty simple.
You might have one question now how to handle click event or those kind of events raised by your view in our View model. It’s pretty easy create a function with same name as your button. Just go back to the View and check the name of the hyperlink button, also check whether their is method with same name in View model. Hyperlink button name is EditCustomer and I have one method in View model EditCustomer. The method will create an instance of another view model.
Later in this post you can see how we can pass parameters from your view to view model.
NotifyOfPropertyChange
In our properties the setter calls a function called NotifyOfPropertyChange, what is the use of this function call? We call this function to notify the UI that the value has changed in the view model. We can notify UI without calling NotifyOfPropertyChange by implementing INotifyPropertyChanged interface and pass the property name. Caliburn Micro wraps the implementation of INotifyPropertyChanged in PropertyChangedBase and our view model is inherited from it. NotifyOfPropertyChange we are not passing any string value instead we pass the Property itself. The advantage of this method is we can use VS refactoring feature on properties. If we pass it as string then refactoring will not take into consideration.
Event Handling
When I implemented MVVM using Caliburn Micro I implemented the communication between View Models using normal event driven mechanism. That means If I want to handle an event occurred in a child view model in the parent. Then child view model raise an event and the parent will handle it. I didn’t like this approach as it creates a dependency between View models. So I start exploring Caliburn Micro to figure out the event handling features and my search ends in EventAggregator.
Caliburn Micro’s Event Aggregator functionality is a very powerful implementation of Observer pattern. We can write View Models with less coupling using EventAggregators. Let’s see how can we establish communication between View Models using Event Aggregator.
In the sample code I created a static property to give access to EventAggregator as shown below
public class EventAggregationProvider { static EventAggregator _eventAggregator = null; public static EventAggregator EventAggregator { get { if (_eventAggregator == null) _eventAggregator = new EventAggregator(); return _eventAggregator; } } }
In the sample app I have a popup window to edit the Customer Details, when the user clicks Save/Ok I need to notify the Parent View Model to initiate the Save process. Let’s see how to implement it.
In my CustomerEditViewModel.cs there is a method called SaveCustomer which will get called when the user clicks Ok from the View. You can see that in SaveCustomer I am publishing the Customer object. See how I am publishing it.
EventAggregationProvider.EventAggregator.Publish<Customer>(customer);
This ViewModel done his job, it’s job of the parent view model who can subscribe to this message and get the notification. Now let’s see how the parent view model is subscribing to this event.
public class CustomerListingViewModel : PropertyChangedBase, IHandle<Customer> {
public CustomerListingViewModel()
{
Messages.EventAggregationProvider.EventAggregator.Subscribe(this);
}
public void Handle(Customer message) { //do the save process }
}
To Subscribe to Customer message the CustomerListingViewModel is implemented by IHandle<Customer>. That means this CustomerListingViewModel is capable of handling any message with type Customer. One more line of code need to added to get notification. You can see in the constructor of CustomerListingViewModel to subscribe to EventAggregator.
Your View Model can subscribe to any number of messages by implementing IHandle with the respective type. For e.g
public class CustomerListingViewModel : PropertyChangedBase, IHandle<Customer>,IHandle<Order> {
public CustomerListingViewModel()
{
Messages.EventAggregationProvider.EventAggregator.Subscribe(this);
}
public void Handle(Customer message) { //do the save process }
public void Handle(Order message)
{
//do the save process
}
}
In the above e.g this View Model will get notified if any view model publish Customer or Order message.
Action Message
The Action Message is one of the functionality of Caliburn Micro to call parameterized function from View. Let’s see how we can do it. To do this we need to refer system.windows.interactivity assembly.
In the below e.g. a message box will show when a LostFocus happened in View EditCustomerView. Let’s go through the View
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:ca="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
<TextBox x:Name="Name" Grid.Row="0" Grid.Column="1"> <i:Interaction.Triggers> <i:EventTrigger EventName="LostFocus"> <ca:ActionMessage MethodName="NameLostFocus"> <ca:Parameter Value="{Binding ElementName=Name,Path=Text}"></ca:Parameter> </ca:ActionMessage> </i:EventTrigger> </i:Interaction.Triggers> </TextBox>
I referenced System.Windows.Interactivity and Caliburn Micro in the View. As you can see in the above view I mentioned “LostFocus” to the EventName. The ActionMessage takes the MethodName that we created in the ViewModel. Parameter’s Value take the parameter to the method. So what’s this means, it’s very simple, whenever the lost focus happened in Name text box then the view should call NameLostFocus method with TextBox’s Text as the parameter. Below is the NameLostFocus method in the ViewModel
public void NameLostFocus(string text) { MessageBox.Show(text); }
You can see more about Action Message in Rob’s blog
Bootstrapping
Bootstrapping is the method of booting our application and allow Caliburn Micro to take the control. So how to create a bootsrapper. It’s very simple as shown below
namespace WCFEnabledSilverlightApp { public class BootStrapper:Bootstrapper<ViewModels.CustomerListingViewModel> { } }
It’s tells caliburn that CustomerListingViewModel is the first page to load. It’s same as setting RootVisual to the some page say MainPage in non MVVM model. We need to provide this BootStrapper in App.xaml as shown below
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="WCFEnabledSilverlightApp.App" xmlns:bs="clr-namespace:WCFEnabledSilverlightApp" > <Application.Resources> <bs:BootStrapper x:Name="bootStrapper"></bs:BootStrapper> </Application.Resources> </Application>
Below is code behind of App.xaml. No code just clean.
using System.Windows; namespace WCFEnabledSilverlightApp { public partial class App : Application { public App() { InitializeComponent(); } } }
This post is just an introduction to Calibun Micro, just use it and get more comfortable with it. Thanks for reading this long post.
Introduction to Caliburn Micro Part 2
Download the source code.