Building a Business Intelligence App using Xamarin.Forms
The MyBI application is a business intelligence application that loads sales data from a Google Sheet. The BI app then summarizes it and produces a simple and effective dashboard that can be used on mobile devices as well as on the desktop.
The Xamarin.Forms version of MyBI was designed to take advantage of both the .NET underpinnings in Xamarin, the potential for shared UI and business logic in XAML and C#. This version of the app demonstrates small but important platform optimizations that we created to give it the best look and feel on each platform.
We have also developed a Progressive Web App (PWA) version of MyBI using Wijmo. PWA’s are another avenue for mobile app development that have been gaining popularity. Xamarin, PWA’s, and native apps each have advantages and weaknesses. Developing the same app using different technologies allowed us to demonstrate the similarities and differences between different platforms.
In another article, I discuss Tips for Building Adaptive Apps with Xamarin.Forms.
The MyBI Xamarin.Forms Application
The Xamarin version of the MyBI application was built using Xamarin.Forms. It uses subtle customizations to achieve a native look and feel on every device. Compared to the PWA version of the MyBI app, this version is tailored to each native platform. The app also previews upcoming changes to the FlexGrid including a new Material Design theme.
The app loads monthly sales data from a CSV, consolidates it, and shows dashboard-style summary information about sales volume and revenue. Users can filter against individual regions or products or look at aggregate results.
This Xamarin.Forms app supports UWP, iOS, and Android, and it spans both desktop and mobile.
The BI Data Source
The Xamarin.Forms MyBI application shares data with the Wijmo version, and it gets similar data from CSV files. The data contains monthly sales and revenue divided among regions and products. We decided to use Google Sheets and CSV because that makes it easy to update and load the data. A manager can open the sheet in his browser, update the data, and it becomes immediately available to the app. There’s no need to save or export anything, and the CSV format is compact and easy to parse on the client.
When it starts, the application attempts to load data from the web first, but if it can’t connect to the internet it also contains a local copy of data. The app assigns the data to a Model class which filters and summarizes it, so it can be shown to users.
The Model class has the following members:
Model Input
- rawData: CSV string with data from the server
- selectedRegion: Name of the selected region, empty to select all regions
- selectedProduct: Name of the selected product, empty to select all products
Model Output
- regions: CollectionView with all regions
- products: CollectionView with all products
- filteredView: CollectionView with consolidated and filtered data
- groupedView: CollectionView with consolidated/filtered/grouped data
The model filters and summarizes data according to the current selection using the CollectionView class and C#.
The application also has an App class that instantiates a Model and uses it to create pages that make up the UI. The pages are contained in a MasterDetailPage arrangement which we’ll cover more.
Pages
- Selection: contains two combo boxes that allow the user to select the region and country. Unlike the Wijmo version, there is no navigation contained in this pane.
- Current Period: contains radial gauges that show the units sold and revenue for the current period. The gauges include ranges that represent ‘target zones’ so users can see the current values.
- Trends: contains charts showing units sold and revenue over time. The charts include trend lines that show whether the values are trending up or down.
- Details: contains a grid that displays units sold and revenue per month. The grid includes linear gauges for the numerical values.
- Info: contains information about the MyBI sample.
Screen Layout and Behavior
The MyBI app is written using Xamarin.Forms. While it’s similar to the PWA, it has some notable deviations in design. The screen layout and behavior more closely match the native capabilities of each platform compared to the PWA version, and, while the functionality remains the same, the look and feel is different.
The MyBI app wraps its pages inside a MasterDetailPage, which consists of a master page that exists as a side panel and a detail page that shows detailed information about an item.
Pages are presented differently depending on the device and platform the app is targeting. On desktop this translates to an ever-present side panel for your application, on phones it becomes a collapsible side panel which a user can display or hide at their discretion, and on tablet it can be configured for either behavior by setting the MasterBehavior property.
The content pages that consist of data visualizations (including Current Period, Trends, and Details) are contained in a TabbedPage.
We chose tabbed pages for this portion of the app since it resembles the Wijmo PWA version in spirit but also has a very native feel. The Xamarin.Forms TabbedPage corresponds to different controls depending on platform, including UITabBar on iOS, TabLayout on Android, and a CommandBar on UWP. There are some obvious differences between each, such as the placement of the tabs, which are on the bottom of the screen on iOS but on the top for Android and UWP.
This highlights one of the fundamental tenants in Xamarin.Forms. While the controls are cross-platform and the code can be shared, the behavior of the control should map to the native look and feel of each platform. Since there are differences between the platforms in approach, a control might not behave precisely the same way on each platform.
Platform Specific Tweaks
Cross-platform development is a balance between working from one common code base and translating that into a UI that feels appropriate for each platform. Each native platform is very distinct. There are many times where the default Xamarin behavior might not be desirable because they’ve made a design compromise that you might not want to make.
Xamarin provides many tools for tweaking behavior on a platform by platform basis, but it requires that you write code that is specific to each platform. This is very different to the PWA approach where your app looks and behaves the same on each platform.
One of the smallest tweaks that you’ll notice in the MyBI app is a platform specific behavior for iOS. Since Apple introduced the iPhone X with the camera “notch” developers have needed to consider this area in their designs. Otherwise, UI elements may be drawn off screen (into the area the notch physically occupies).
To avoid this every XAML page has two lines of code at the top:
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" ios:Page.UseSafeArea="true"
Xamarin provides a built-in platform specific behavior to handle this (UseSafeArea), but it’s up to developers to make use of it. You can also make changes on a per platform basis by adding code into each of the platform projects contained in a Xamarin.Forms solution. For instance, you may have noticed that the tabs are not only placed differently when comparing iOS and Android, but they also are colored differently.
On iOS, it’s more typical to use an accent (or tint) color for highlighting the selected tab. On Android it treats this differently by placing a cursor under the selected item and using an accent color for the background.
Xamarin.Forms doesn’t easily let you configure this from shared code, so to get the tinted selection on iOS we need to add extra code to the AppDelegate class in the iOS project.
UITabBar.Appearance.TintColor = UIColor.FromRGB(63, 81, 181);
This is only scratching the surface, and Xamarin offers many tools for platform specific changes including the Custom Renderers, Effects, and Platforms Specifics.
There are many tools for this, and, if you have more interest in the topic, we recommend checking out our white paper on how to build a custom control in Xamarin.Forms. These platform specific changes aren’t always a tweak to the UI, and they can also be used to optimize for a given platform.
MYBI Performance
Xamarin.Forms produces native code (which can be just as fast as writing in Java or Swift), but there are some caveats to this and optimizations that we can make. The performance of Xamarin.Forms applications on Android has always been a little slow, and these apps have added complexity in their visual trees compared to what can be produced writing native code in Java. The Android platform is particularly sensitive to this and it can have a negative performance impact.
In the past year, Xamarin has begun to add new optimizations that developers can take advantage of to improve the performance of their apps. The first optimization to the application is to enable XAML Compilation so that XAML is compiled into an intermediate language. Compiling gives early indication of any problems with the code and passes notifications on to the developer.
It also improves the load and instantiation time for XAML elements. Finally, compiling also can impact the file size of the final assembly since it’s no longer necessary to include the .xaml files.
These benefits are passed on to all platforms.
It’s an easy optimization to make since all you need to do is add the following line to the code behind of your XAML pages:
[XamlCompilation(XamlCompilationOptions.Compile)]
The second optimization is to use Layout Compression, specifically in the FlexGrid within Details section. Layout compression attempts to flatten layers of views by removing specified layouts from the visual tree, and it can lead to improved page rendering performance.
The performance increase is highly dependent on the complexity of the nested view hierarchy in the page, the relative performance of the device, and the operating system it runs on. Generally, older devices will see the largest improvements.
To enable Layout Compression on a layout class you need to set CompressedLayout.IsHeadLess to True. For instance, when we use this technique within the FlexGrid in the CellTemplate for the revenue column, it appears as follows:
<flexgrid:GridColumn.CellTemplate> <DataTemplate> <Grid CompressedLayout.IsHeadless="true"> <gauge:C1LinearGauge IsAnimated="False" Value="{Binding SumRevenue}" Max="{Binding MaxRevenue}" IsReadOnly="True" PointerColor="#AA73B049" /> <Label Text="{Binding SumRevenue}" HorizontalTextAlignment="Center" VerticalOptions="Center"/> </Grid> </DataTemplate> </flexgrid:GridColumn.CellTemplate>
Since this layout is reused many times, it can add up to a noticeable performance benefit, and the technique is also used for the CellTemplate in the unit column. This performance improvement is only applicable to iOS and Android.
The final optimization is activating the Fast Renderers for Android. Fast renderers are another mechanism for reducing the complexity of the visual tree and flattening it, which can lead to a reduction in inflation and rendering costs.
Xamarin generally composes their controls in two parts, the native control and a container for it that handles layout and gestures. This creates extra overhead for some controls since it’s effectively creating two views rather than one in most circumstances. Fast renderers remedy this by only using one view for certain controls rather than two, and it can contribute to a much less complex visual tree. Fast renderers are only presently available for Label, Image, and Button controls, but since these are all very commonly used it can have a noticeable impact on your app’s performance.
To enable fast renderers, you need to add a line of code to your MainActivity class before calling Forms.Init() in your Android project within you Xamarin.Forms solution:
Xamarin.Forms.Forms.SetFlags("FastRenderers_Experimental");
Fast renderers only apply to Android and the app compat backend, and the feature is currently experimental. However, it can yield tangible performance benefits, especially scrolling through a ListView or FlexGrid with many rows of data.
MyBI: A Native Mobile App and a PWA
The MyBI app is available as both a native mobile application, which we’ve showcased using our Xamarin components, as well as a PWA using our Wijmo JavaScript components.
The Xamarin.Forms MyBI app is available for now via the GooglePlay Store and the Windows Store.
We’ll be shipping the sample as part of our 2018 v3 release.
The two apps should contrast the capabilities of each cross-platform approach, but still use very similar data, business logic, and components.
Feel free to contact us with any comments, questions, or suggestions in the ComponentOne Studio for Xamarin forum.