Tag Archives: MVVM

Video Tutorial: Creating Your First Crosslight App

For those of you new to cross-platform development, fear not. Crosslight is here to the rescue. Building cross-platform apps has never been easier using Crosslight. Crosslight is a cross-platform toolset that helps you to create cross-platform apps using C#, leveraging the MVVM pattern. If you haven’t got a copy of Crosslight, grab one here!

To help you get started, we have just released a new video tutorial that will help you to create your first Crosslight app using the Crosslight Project Wizard and run the project on all four platforms: iOS, Android, Windows Phone and Windows Store.

Find out more about Crosslight at our Developer Center. Also checkout our newbie-proof Crosslight tutorial. If you have any questions, feel free to post it in our community forum, or drop us a mail.

Video Tutorial: Getting Started with Crosslight Reporting Service

Crosslight 2 provides a capability to view enterprise reports across multiple platforms including iOS, Android, Windows Phone and Windows 8. The reporting services is built upon the company’s flagship reporting, ClientUI Reporting, to produce identical reports across multiple platforms. You can quickly add reporting feature to your apps since Crosslight has encapsulated all of the functionality required to display the reports on multiple platforms natively. Check out the following video to learn how to configure the report server and display the report on Crosslight apps, which runs on four major platforms: iOS, Android, Windows Phone 8 and Windows Store.

You can also get the source code for this video from our new Git server: http://git.intersoftpt.com/projects/CROS-SUPP/repos/simple-reporting/browse. To learn more about Crosslight reporting service and how it works, see Viewing Enterprise Reports. If you have any questions, feel free to post it in our community forum, or drop us a mail.

Advanced Batch Update with MVVM support in Crosslight iOS

If you are iOS users, you might already familiar with the Mail app. When new messages arrived, notice that the new items are inserted smoothly with beautiful animation. The implementation for such insertion is in deed challenging since it needs to take account the actual insertion position based on the sorted data. Furthermore, multiple insertions are also supported with simultaneous animation which adds complexity to the logic. Technically, inserting an item will cause the index of remaining items invalid — and not to mention if there are deletion along the process. There are a lot of aspects that need to be considered. In this blog post, I will share how we support this user experience seamlessly in Crosslight 2.

iOS supports this simultaneous updates through a feature called batch updating. Implementing this feature requires deep knowledge of how iOS works — and typically what you want to avoid, particularly if your code is targeting multiple platforms. Thankfully, Crosslight has supported this batch update operation since its first version by allowing you to simply perform updates to your collection in .NET way. You don’t need to know about iOS even a bit.

Recently, we made several improvements to Crosslight for batch update support in a sorted collection. This allows you to simply adding items or deleting items on a sorted collection without concerning the actual position where it will be displayed or removed. The Crosslight’s table view component now takes care everything behind the scene, including the batch updating process, maintaining the delta changes and simultaneously animate the changes.

Consider you have a raw collection of countries: US, China, Japan, Netherlands, and Greece. When bound to the view, the collection is sorted by the country name in ascending with LINQ. At runtime, you then add few more countries: Indonesia, Brazil, and Mexico.

In ViewModel, the C# code looks like below.

public class BatchUpdateListViewModel : EditableListViewModelBase<Country>
{
    public DelegateCommand BatchUpdateCommand { get; set; }

    public BatchUpdateListViewModel()
    {
        var items = new List<Country>();
        items.AddRange(Countries.Create("US", "China", "Japan", "Netherlands", "Greece"));

        // just a plain .NET collection here
        this.SourceItems = items.ToObservable();

        this.BatchUpdateCommand = new DelegateCommand(ExecuteBatchUpdate);
    }

    private void ExecuteBatchUpdate(object parameter)
    {
        // Begin batch updating
        this.IsBatchUpdating = true;

        // Perform multiple inserts simultaneously to the source items
        this.SourceItems.Add(new Country("Indonesia"));
        this.SourceItems.Add(new Country("Brazil"));
        this.SourceItems.Add(new Country("Mexico"));

        // End batch updating
        // After this code, the bound list view will be automatically updated with smooth animation
        this.IsBatchUpdating = false;
    }

    protected override void OnSourceItemsChanged(ICollection<Country> items)
    {
        // Sort the source items by country name, and use the sorted collection for the display items
        this.Items = items != null ? items.OrderBy(country => country.Name) : null;
    }
}

Notice that the above code simply adds items to the source collection, you don’t have to concern the actual positions in the view. The only thing you need to ensure is to perform the collection changes while the IsBatchUpdating property value is true. As soon as the property is set to false, the bound view will be automatically notified and perform the animation simultaneously. This simple and intuitive code lets you to achieve the stunning user experience similar to Apple’s built-in Mail app when new items are added dynamically at runtime.

The following illustration shows what happened to the sorted collection at runtime.

BatchUpdateIllustration

To demonstrate this feature, we have added a new Sorted Batch Update to the Data Samples which you can download from our Git server. The bits is under the batch-update-sorted branch. You’ll also need nightly build (revision 54 or higher) to try out this new improvement.

In addition to multiple insertions, the sample also demonstrates multiple deletion. And to add more complexity, it also modifies the items which cause its order to change. For your convenience, you can see how the sample works below.

Improved batch update support on sorted collection

 

Most cross-platform frameworks I found today provide just a set of API without thoughtful consideration of the user experience that native to the platform. That’s where Crosslight sets apart. More than just a set of API, we designed Crosslight with the simplicity you expected, while taking account many other important factors behind the scene which will make your apps shine.

Join us for a 3-day live webinars on June 10 – 12, and learn how you can build great cross-platform business apps with Crosslight. We will be demo’ing how to create a fully-functional CRM app in just mere minutes — live. Seat is limited, so reserve yours now.

Video Tutorials: Understanding MVVM Pattern and Building Simple Tip Calculator App with Crosslight

We have released two new video tutorials on Crosslight to help you better understand how to develop better mobile applications using Crosslight.

Understanding MVVM Pattern in Crosslight

This video tutorial outlines in general how the MVVM pattern works in Crosslight apps development. You will learn how Crosslight leverages the MVVM concept in order to produce cross-platform projects with a single shared application layer. By the end of this video, you will be able to grasp the MVVM pattern in general as well as getting the right mindset when building apps using Crosslight.

Building Simple Tip Calculator using Crosslight

This video tutorial explains how you can build a simple tip calculator app using Crosslight  within minutes that target all four major platforms at once (Android, iOS, Windows Phone, Windows 8). This video aims to highlight the data binding capabilities in Crosslight that leverages the MVVM pattern found in .NET applications to mobile apps development. You can find the source code for this video in our GitHub link: https://github.com/IntersoftSolutions/CrosslightSimpleTipCalculator

Should you have any further questions, feel free to contact us at technical@intersoftpt.com or raise a thread in our forums. Hopefully this video will give you a clearer concept how Crosslight works and how you can slash development time in more than half and increase your productivity. Stay tuned for more Crosslight video tutorials. Don’t forget to subscribe to our YouTube channel as well!

Cheers,
Nicholas Lie

Cross Platform Mobile Development with Crosslight – Part 2

This is the second post of cross-platform mobile development with Crosslight series. Continuing from the previous post , I am most pleased to share two of the exciting features shipped with Crosslight: unified navigation framework and powerful data binding.

Unified Navigation Framework

As navigation differs from one mobile framework to another, it’s a challenging task for mobile developers to streamline the navigation logic all in one place that can work consistently between platforms. Take iOS, Android, Windows Phone, and WinRT for example. iOS uses push navigation while Android uses Intent-based navigation while Windows Phone and WinRT use Page-based navigation. Gone are the days you will have to worry about these troubles with Crosslight. This section will outline the features supported by Crosslight navigation framework.

Basic Navigation

Crosslight navigation supports basic navigation to a page using the view model.  This is achieved using the navigation service from the view model and calling the Navigate method then specify the desired view model to navigate. It’s as simple as that.

Basic Navigation on iOS

At its simplest form, basic navigation can simply be done with the following simple calls from the view model:

private void ExecuteNavigateIdentifier(object parameter)
{
    this.NavigationService.Navigate("ViewModel1Derivative");
}

private void ExecuteNavigateParameter(object parameter)
{
    // You can pass any objects as parameter during navigation
    this.NavigationService.Navigate(new NavigationParameter(parameter));
}

private void ExecuteNavigateType(object parameter)
{
    this.NavigationService.Navigate();
}

Note that you can also navigate to the same view model but consumed by different views using the NavigationParameter as shown above.

List Navigation (Push Navigation)

Crosslight navigation service enables you to perform navigation from within the view model. You can navigate to a view model by providing the type, or a known identifier.

Unified List Navigation on WIndows Phone

The navigation view model looks as simple as this:

public class NavigationViewModel : ListViewModelBase
{
    public NavigationViewModel()
    {
        IApplicationContext context = this.GetService().GetContext();

        List items = new List();

        items.Add(new NavigationItem("Simple List", "Data View", typeof(SimpleListViewModel)));
        items.Add(new NavigationItem("Grouped List", "Data View", typeof(GroupListViewModel)));
        items.Add(new NavigationItem("Grouped List (Section)", "Data View", new NavigationTarget(typeof(GroupListViewModel), "GroupStyle")));
        items.Add(new NavigationItem("Grouped List with Index", "Data View", new NavigationTarget(typeof(GroupListViewModel), "GroupIndex")));
        items.Add(new NavigationItem("Searchable List", "Data View", typeof(FilterListViewModel)));
        
	...

        this.SourceItems = items;
        this.RefreshGroupItems();
    }

    public override void RefreshGroupItems()
    {
        if (this.Items != null)
            this.GroupItems = this.Items.GroupBy(o => o.Group).Select(o => new GroupItem(o)).ToList();
    }
}

Modal Navigation

The integrated navigation service supports a special navigation type called as modal navigation. It is particularly useful to present a view that waits for user input; you can return a navigation result indicating whether the user provided the input or cancelled the input, as well as capturing additional data as the result of the modal navigation.

Modal Navigation on Android

To execute a modal navigation, in the view model, we can specify as follows:

private void ExecuteNavigateModal(object parameter)
{
    NavigationParameter navigationParameter = new NavigationParameter()
    {
        NavigationMode = NavigationMode.Modal
    };

    ...

    this.NavigationService.Navigate(
        new NavigationTarget(typeof(ViewModel3), navigationParameter),
        (result) =>
        {
            if (result.Action == NavigationResultAction.Cancel)
                this.MessagePresenter.Show("You cancelled the data input");
            else
                this.MessagePresenter.Show("You entered: " + result.Data.ToString());
        });
}

Notice that after modal navigation is executed, you can handle the result of the modal navigation through action callbacks.

Nested Modal Navigation

In addition to basic modal navigation, the Crosslight navigation service also supports advanced modal navigation that allows you to perform navigation within the modal view context. Called Nested Modal Navigation, this feature is particularly useful when you need to capture numerous data input that are split to multiple views (wizard-like).

Nested Modal Navigation on WIndows Phone

The navigation service manages the navigation stack made during the modal session. When the Close method is called, it automatically discards the entire modal navigation stack, and return to the initiator view.

Nested Modal Navigation Result on Windows Phone

It is quite simple to execute a nested modal navigation:

private void ExecuteNavigateModal(object parameter)
{
    NavigationParameter navigationParameter = new NavigationParameter(new RegistrationData())
    {
        NavigationMode = NavigationMode.Modal,
        EnsureNavigationContext = true
    };

    this.NavigationService.Navigate(
        new NavigationTarget(typeof(NestedStep1ViewModel), navigationParameter),
        (result) =>
        {
            if (result.Action == NavigationResultAction.Cancel)
                this.MessagePresenter.Show("You cancelled the data input");
            else
                this.ShowRegistrationData(result.Data as RegistrationData);
        });
}

Similar to the previous modal navigation, you can handle the result of the nested modal navigation through action callbacks through the nested modal view initiator.

Master-Detail Navigation

The Crosslight navigation service supports master-detail navigation, both when deployed to a phone device or a tablet device. On a phone device, the navigation would be interpreted as push navigation while on a tablet it would be treated differently based on the targeted platform.

On phone, it will look like this:

Master Detail Navigation on Phone

While on tablet:

Master Detail Navigation on Tablet

For iOS and Android, you would need a binding provider that specifies the detail view model when the item is tapped.

public class ListNavigationBindingProvider : BindingProvider
{
    #region Constructors

    public ListNavigationBindingProvider()
    {
        ItemBindingDescription itemBinding = new ItemBindingDescription()
        {
            DisplayMemberPath = "Name",
            DetailMemberPath = "Location",
            ImageMemberPath = "ThumbnailImage"
        };

        this.AddBinding("TableView", BindableProperties.ItemsSourceProperty, "Items");
        this.AddBinding("TableView", BindableProperties.ItemTemplateBindingProperty, itemBinding, true);
        this.AddBinding("TableView", BindableProperties.SelectedItemProperty, "SelectedItem", BindingMode.TwoWay);
        this.AddBinding("TableView", BindableProperties.DetailNavigationTargetProperty, new NavigationTarget(typeof(ItemDetailViewModel)), true);
    }

    #endregion
}

Tab Navigation

The navigation service also supports tab navigation using selected index. By inheriting a special view model called MultiPageViewModelBase, you can perform navigation setting the selected index of the navigation items. You can also send parameters and custom objects during tab navigation.

Tabbed Navigation on iOS

The TabViewModel that enables tab navigation:

public class TabViewModel : MultiPageViewModelBase
{
    #region Constructors

    public TabViewModel()
    {
        var items = new List();
        items.Add(new NavigationItem("Simple Page", typeof(SimpleViewModel)) { Image = "first.png" });
        items.Add(new NavigationItem("About", typeof(AboutNavigationViewModel)) { Image = "second.png" });

        this.Items = items.ToArray();
    }

    #endregion
}

Powerful Data-Binding Features

Crosslight was designed with the powerful MVVM design pattern in mind. The MVVM design pattern itself is almost always associated with data-binding concept. .NET developers targeting Silverlight and WPF will be at home with the concept. However, this post will not cover the concepts of data-binding itself, but more on how Crosslight leverages this concept to the mobile development world, which were only available to platforms such as Silverlight and WPF. If you would like to learn more about data-binding concept, Microsoft has detailed a very good article here that covers the topic in-depth.

Property-to-Property Binding

Crosslight data-binding framework supports the very basic property-to-property data binding, enabling you to bind a property to another property using various information contained in BindingDescription using a BindingProvider class.

public class BindingModeBindingProvider : BindingProvider
{
    public BindingModeBindingProvider()
    {
        this.AddBinding("Label1", BindableProperties.TextProperty, "Text", BindingMode.OneTime);
        this.AddBinding("Label2", BindableProperties.TextProperty, "Text", BindingMode.OneWay);
        this.AddBinding("TextField1", BindableProperties.TextProperty, "Text", BindingMode.TwoWay);
        this.AddBinding("Label3", BindableProperties.TextProperty, "Amount", BindingMode.OneWay);
        this.AddBinding("Slider1", BindableProperties.ValueProperty, "Amount", BindingMode.TwoWay);
        this.AddBinding("TextField2", BindableProperties.TextProperty, "Amount", BindingMode.TwoWay);
        this.AddBinding("Stepper1", BindableProperties.ValueProperty, "Amount", BindingMode.TwoWay);
    }
}

Universal Data Management

Crosslight data binding framework supports automatic UI updates when bound to a collection. This allows for easier data management as well as saving you the trouble of updating the UI when the underlying data model changes. Consider the following view model:

private void ExecuteBatchUpdate(object parameter)
{
    // Begin updating
    this.IsBatchUpdating = true;

    // Perform multiple add and remove simultaneously
    var items = this.Items.ToObservable();
    var updatedItem = items.ElementAt(0);

    updatedItem.Name = "Modified at " + DateTime.Now.ToString("hh:mm:ss");
    this.OnDataChanged(updatedItem);

    items.Insert(1, new Item {Name = "New Item " + this.NewIndex++, Location = "New warehouse", ThumbnailImage = updatedItem.ThumbnailImage});
    items.Insert(3, new Item {Name = "New Item " + this.NewIndex++, Location = "New warehouse", ThumbnailImage = updatedItem.ThumbnailImage});
    items.Insert(6, new Item {Name = "New Item " + this.NewIndex++, Location = "New warehouse", ThumbnailImage = updatedItem.ThumbnailImage});

    items.Remove(items.ElementAt(5));
    items.Remove(items.ElementAt(7));

    this.ToastPresenter.Show("Added 3 items, removed 2 items, updated 1 item", null, null, ToastDisplayDuration.Immediate, ToastGravity.Center);

    // End updating
    this.IsBatchUpdating = false;
}

After you have finished inserting items to the model, the view updates accordingly.

Universal Data Management on iPhone

Binding to Nested Property

Aside from binding to a top-level property, you can also bind to a nested property.

Binding to Nested Property on WinRT

Case 1: Loan Calculator

Loan Calculator

A simple app that can be made using the data-binding framework is the loan calculator where you would input the amount of loan, the loan term in years, and the interest rate per year.

Loan Calculator Result on Android

Each of the textboxes and the button is bound using a BindingProvider.

public class LoanCalculatorBindingProvider : BindingProvider
{
    public LoanCalculatorBindingProvider()
    {
        this.AddBinding("AmountTextField", BindableProperties.TextProperty, "Amount", BindingMode.TwoWay);
        this.AddBinding("LoanTermTextField", BindableProperties.TextProperty, "LoanTerm", BindingMode.TwoWay);
        this.AddBinding("InterestRateTextField", BindableProperties.TextProperty, "InterestRate", BindingMode.TwoWay);
        this.AddBinding("MonthlyPaymentLabel", BindableProperties.TextProperty, new BindingDescription("MonthlyPayment") { StringFormat = "{0:c}" });
        this.AddBinding("CalculateButton", BindableProperties.CommandProperty, "CalculateCommand");
    }
}

After inputting the specified amount, loan term, and interest rate, and hit calculate, it calculates the monthly payment by calling the command specified in the view model, as follows:

private decimal GetCalculateMontlyPayment()
{
    return decimal.Round((this.Amount + (this.Amount * this.InterestRate * (decimal)this.LoanTerm)) / ((decimal)this.LoanTerm * (decimal)12),2);
}

Case 2: Currency Converter

Another simple example would be to make an offline currency converter. This example demonstrates Crosslight support for binding with full converter and UpdateSourceTrigger support.

Currency Converter

Full Converter Support

Just like the native binding found in Silverlight and WPF platforms, Crosslight also supports binding with converter, complete with converter parameter and converter culture.

UpdateSourceTrigger Support

Intersoft Crosslight provides four predefined UpdateSourceTrigger values, namely Default, Explicit, LostFocus, and PropertyChanged. By default, the update process to the bound property will be done after lost focus event is triggered. The following code shows how you can use the two-way BindingMode as well as setting the UpdateSourceTrigger to PropertyChanged.

public class CurrencyConverterBindingProvider : BindingProvider
{
    public CurrencyConverterBindingProvider()
    {
        CurrencyFormatConverter converter = new CurrencyFormatConverter();

        this.AddBinding("BaseCurrencyTextField", BindableProperties.TextProperty, new BindingDescription("USCurrency", BindingMode.TwoWay, UpdateSourceTrigger.PropertyChanged));
        this.AddBinding("BritishCurrencyTextField", BindableProperties.TextProperty, new BindingDescription("UKCurrency") { Converter = converter, ConverterParameter = "{0:c}", ConverterCulture = new CultureInfo("en-gb") });
        this.AddBinding("EuroCurrencyTextField", BindableProperties.TextProperty, new BindingDescription("EuroCurrency") { Converter = converter, ConverterParameter = "{0:c}", ConverterCulture = new CultureInfo("nl-NL") });
        this.AddBinding("SGCurrencyTextField", BindableProperties.TextProperty, new BindingDescription("SGCurrency") { Converter = converter, ConverterParameter = "{0:c}", ConverterCulture = new CultureInfo("zh-sg") });
        this.AddBinding("AUCurrencyTextField", BindableProperties.TextProperty, new BindingDescription("AUCurrency") { Converter = converter, ConverterParameter = "{0:c}", ConverterCulture = new CultureInfo("en-au") });
    }
}

As a result, the respective currencies will be converted in real time when the text is changed.

Currency Converter on iOS

StringFormat Support

Crosslight BindingProvider also supports binding with StringFormat support.

StringFormat Support on Windows Phone

public class StringFormatBindingProvider : BindingProvider
{
    public StringFormatBindingProvider()
    {
        this.AddBinding("Label1", BindableProperties.TextProperty, new BindingDescription("Amount", BindingMode.OneWay) { StringFormat = "{0:c0}" });
        this.AddBinding("Label2", BindableProperties.TextProperty, new BindingDescription("Amount", BindingMode.OneWay) { StringFormat = "{0:###,###.00}" });
        this.AddBinding("Label3", BindableProperties.TextProperty, new BindingDescription("Date", BindingMode.OneWay) { StringFormat = "{0:g}" });
        this.AddBinding("Label4", BindableProperties.TextProperty, new BindingDescription("Date", BindingMode.OneWay) { StringFormat = "{0:F}" });

        this.AddBinding("Slider1", BindableProperties.ValueProperty, "Amount", BindingMode.TwoWay);
        this.AddBinding("DatePicker1", BindableProperties.ValueProperty, "Date", BindingMode.TwoWay);
    }
}

Wrap-up

Navigation and data-binding are just some of the features Crosslight introduced to the mobile development world. It is important to note while all these features are shown platform specific, they work consistently across multiple platforms. The diverse pictures shown in this blog post is to give you an overview about the features described earlier were not platform-specific; they can be applied cross-platform. Some of the Crosslight API outlined in the code snippets are not explained in detail here; they will be covered comprehensively in our product documentation upon release. You might wonder, while these features sound too good to be true, in fact, they really are. These magical features will be available as soon as we hit our 2013 R1 milestone, which is going to be released very soon in early September.

Regards,

Nicholas Lie