Recently I have received a few questions on a possibility of using the Mobile MVC framework with a "single form/multiple panels" technique when creating a mobile UI's. This technique of having a single form with multiple panels instead of multiple forms is an old practice that existed at the time of eVB. At the time each form load was taking a measurable amount of time and developers were trying to make navigation from view to view to be a more user friendly experience.
The Mobile MVC was created to support "single form/multiple panels" technique as well. It contains the ViewControl class that should be used to become a view and host other controls. I've updated the Mobile MVC solution to include the MultiPanelTest project that demonstrates the usage of the ViewControl. The project contains a single form - MainForm that hosts the views. The add a view, I added UserControl to the project, placed the controls and changed the code to inherit from the ViewControl instead of UserControl. The Visual Studio will conveniently create for us the (View).Designer.cs class as well.
public partial class LoginView : ViewControl
{
public LoginView()
InitializeComponent();
}
In most cases I've just copied the existing code from the MVCTestClientContainer project into the LoginView, SearchView and their corresponding LoginController and SearchController classes. I've also added the following method to the ApplicationManager class:
public static void InitializeViews(Form form)
LoginController loginController = container.Resolve<LoginController>();
loginController.Initialize();
Control view = loginController.View as Control;
view.Size = new Size(240, 250);
form.Controls.Add(view);
view.Hide();
SearchController searchController = container.Resolve<SearchController>();
Control searchView = searchController.View as Control;
searchView.Size = new Size(240, 250);
form.Controls.Add(searchView);
searchView.Hide();
This method is used to add views to the host form and is called from the MainForm's constructor. Other than that the code is stayed the same. Feel free to download the latest from the codeplex.
However before you jump and start using "single form/multiple panels" technique, a few important things should be taken into consideration. First of all, a multiple controls and all associated umnanaged recources (window handles, message pumps, graphic contexts etc...) would be created. Eeach would take device's memory and processor cycles plus the data required to populate the contols. So you should always measure how your application would be affecting the performance of the device or how it would behave in a more memory constrained scenarios.
Secondly, this techinque could affect the load time of your form when it's shown the first time. You may need to show a splash screen to a user to make him/her know that something is happening.
I would like to wish every reader of my blog a Happy New Year and a happy, healthy, prosperous 2010. It's also customary to overview the passed year and summarize on what have been achieved or missed. So here's the digest of the best posts of 2009 in the order of the most hits:
- Generic control creation.
- Dimming the background.
- Update to MobileMVC with Container
- Functional WinForms (or Generic Control Creation 2)
- Porting IPhone applications to Windows Mobile
- Identifying VGA resolution on WM devices.
- A few tips on customizing ListView in WM 6.5
Enjoy :)
There’s been an explosion of the web and cloud related development tools and services such as Web 2.0, RIA’s, Silverlight, multiple cloud services, AZURE etc… Big companies (including Microsoft) have been pushing to move away from fat clients to a thinner clients consisting mostly of the browser. This is all great and understandable however looking at all these developments from the point of utilizing all this power on the Mobile Devices, there are all lacking acknowledgement of a few important issues. The first one is the device connectivity. The reality is that DEVICES ARE NOT ALWAYS CONNECTED… period. So if you are running this fabulous AJAX and JSON (or Silverlight) enabled application in the browser, as soon as the device goes in the area with no wireless reception (travelling, blind spots, subway, basement, elevator, hiking, etc…) your application becomes un-useful unless… there’s an ABILITY TO CACHE THE DATA ON THE DEVICE. This is in most cases restricted by the browser sandbox.
Oh wait there more… What if you would want to detect the connectivity or make use of all these magnificent peripheral devices (Bluetooth, GSP, orientation sensor, etc…) that are becoming a part of most of the smart mobile gadgets these days? Nope. You can’t do it either. The point of this rant is that in the middle of the noise and the hype of the advancing technology; let’s not forget about may be more complex but important solutions that have been proven to work for many years in the past – Rich Client applications that allow full access to the local resources with a combination of data syncing and caching technologies. The user experience matter. If the application becomes unresponsive just because I am in the elevator, it’s a bad user experience. If the application displays “Page not found” error while in the middle of retrieving customer data, it’s a bad user experience. So let’s be realistic.
Last time I showed you on how to customize ListView control on WM 6.5 for .NET CF 3.5. Today I am going to show you a few more. They are all based on the same paradigm - changing an extended style of a ListView control. First one is to enable showing grid lines:
/// <summary>
/// Shows grid lines in the listview
/// </summary>
/// <param name="listView">ListView instance</param>
public static void ShowGridLines(this ListView listView)
// Retreive the current extended style
int currentStyle = SendMessage(listView.Handle,
(uint)LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
// Assign the LVS_EX_GRIDLINES style
SendMessage(listView.Handle, (uint)LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
currentStyle | LVS_EX_GRIDLINES);
And the second one is to enable double-buffering. This should reduce flickering when scrolling on changing the focus from one item to another:
/// Enable double-buffering in the listview
public static void EnableDoubleBuffering(this ListView listView)
// Assign the LVS_EX_DOUBLEBUFFER style
currentStyle | LVS_EX_DOUBLEBUFFER);
Please find the updated ListViewExtender class in the attachments to this post.
Would you like to have ListView control in your .NET CF application on Windows Mobile 6.5 to have this fancy gradient item selections (they are defined by the current theme on the device)?
The secret is in the extended style LVS_EX_THEME that needs to be applied to a ListView. It could be done by sending LVM_SETEXTENDEDLISTVIEWSTYLE to the control. I've wrapped appropriate P/Invoke calls in the following extention method:
/// Sets theme style to a listview
public static void SetThemeStyle(this ListView listView)
// Assign the LVS_EX_THEM style
currentStyle | LVS_EX_THEME);
But wait but there's more... While looking up the values for the P/Invoke messages in the commctrl.h, my eyes cought the forgotten LVM_SETBKIMAGE message which could be used to assign a background image to a ListView. This is how another extention method would look like:
/// Sets background image to a listview
/// <param name="listView">ListView instance.</param>
/// <param name="path">string path to an image.</param>
public static void SetBackgroundImage(this ListView listView, string path)
// Create bitmap
Bitmap bitmap = new Bitmap(path);
// Retrieve HBITMAP
IntPtr hBitmap = bitmap.GetHbitmap();
// Dispose the managed bitmap
bitmap.Dispose();
// Prepare structure
LVBKIMAGE lvImage = new LVBKIMAGE();
lvImage.hbm = hBitmap;
lvImage.ulFlags = LVBKIF_SOURCE_HBITMAP;
// Assign an image
SendMessage(listView.Handle, LVM_SETBKIMAGE, 0, ref lvImage);
The SetBackroundImage method should also work on all WM 6.0 - 6.5 devices.
The you can use these methods should be pretty obviouse:
this.listView1.SetThemeStyle();
this.listView1.SetBackgroundImage(@"\My Documents\My Pictures\Water.jpg");
And the resulting screenshot:
As usual you can download the demo project that contains all the code including P/Invoke declarations.
I have been invited to speak at the Teched conference (Platforma 2010) in Russia. I will be speaking about a wide range of topics on development for Windows Mobile 6.5 plartform such as UI Framework, Gesture API's and Widgets. Marat is going to help me with a part of the presentation. This should be somewhat challenging for me, since I will be presenting in my native (Russian) language and I have not done it in long time (15 years) and I will also need to figure out how a certain terminology is translated into Russian. So if you are in Moscow on November 12 and attending the conference feel free attend my presentation.
Ron and I did a part 1 of the Webcast on the Gesture APIs in the Windows Mobile 6.5 and a managed wrapper that we created. In this Webcast we talked about GestureRecognizer class. You can catch a recording from here:
http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=en-US&EventID=1032422141&CountryCode=US
In the Part 2 we will be describing the Physics engine and WAG functionality of the Gesture API's. You can register for this webcast here:
http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032422150&Culture=en-US
The code for the managed wrapper is available at:
http://code.msdn.microsoft.com/gestureswm
Enjoy!
An interesting article has been recently published on Msdn that describes the real-world experiences of porting the IPhone application to the Windows Mobile platform.
When reading the article I was pleasantly surprised to find out that the developers end up using my UI framework to reproduce look and feel of the IPhone application. It is very satisfying to know that my work is useful.
Take a look at this great introduction into the world of touch screens and gestures by Marcus. He also starts describing the APIs that are available in Windows Mobile 6.5 for handling gestures.
There's a new company that has just released a few really nice controls for .NET Compact Framework and which you can use to develop attractive UIs in your Windows Mobile applications:
http://www.beemobile4.net/
They where nice to let me know that they've learned a lot from my blog and webcasts on creating cool UI's. It is really satisfying that the work that I do is useful for Mobile developers.
The Windows Mobile 6.5 Developer Tool Kit is available for download. It includes the Emulator images as well as the documentation and the samples on Gesture APIs.
Very often when developing managed applications you need to target both VGA (480x640) and the older QVGA (240x320) type of devices. If the AutoScaleMode property of your form is set to Dpi, your controls such as textboxes. labels, buttons etc... will be scaled automatically. However if your draw images yourself or utilizing the ImageList, the images are not going to be autoscaled for you. During the runtime you can easily identify the VGA resolution by using the following code:
public static bool IsHighResolution(this Form form)
SizeF currentScreen = form.CurrentAutoScaleDimensions;
if (currentScreen.Height == 192)
return true;
return false;
This is an extension method which is a part of the ControlExtension class from the ListViewDemo project which you can download from here.
So how would you use that method. Here's a sample function that you can place in your form's code:
private void HandleHiRes()
if (this.IsHighResolution())
this.imageList1.ImageSize = new Size(32 * 2, 32 * 2);
Enjoy...
Sean Kelley who is the PM for the Sync Services for ADO.NET has recorded a webcast that walks through the new features of the next version of the SyncServices. The team has collected a lot of the feedback from the customers on the first version and tried to incorporate it into vNext. The notable changes are: ability to create database snapshots, P2P synchronization, batching, etc... Check out the Sean's webcast for more details:
https://msevents.microsoft.com/CUI/Register.aspx?culture=en-US&EventID=1032413045&CountryCode=US&IsRedirect=false
My article on the UIFramework that I presented during my webcasts has been published on MSDN:
http://msdn.microsoft.com/en-us/library/dd630622.aspx
I've recently made a substantial update to the MobileMVC framework. I've added the ability to utilize a (D)epenendcy (I)njection container by adding IControllerProvider interface into the framework which looks like this:
public interface IControllerProvider
Controller GetController(string name);
Controller GetController(Type type);
Controller GetController<T>();
Controller GetController<T>(IView view);
void RegisterController(Controller controller);
This interface gets used in the new class Navigator which could be used instead of NavigationService to navigate between the controllers since it implements the same methods such as Navigate, GoBack, GoForward etc... The Navigator class is exposed as a singleton via the property in the Controller class:
/// Gets an instance of the Navigator.
public Navigator Navigator
get
return Navigator.Current;
The Navigator class also includes the following static method:
/// Sets the IControllerProvider to use.
/// <param name="controllerProvider"></param>
public static void SetControllerProvider(IControllerProvider controllerProvider)
if (navigator == null)
navigator = new Navigator(controllerProvider);
As you can see the SetControllerProvider method accepts as a parameter an instance of the IControllerProvider which you will need call when your application is initialized.
Before diving into the full usage sample let's talk about the DI container. As we know, there's not much of the DI and IoC containers exist for .NET CF right now, however Paterns & Practices team has been quetly working on the update of the Mobile Application Blocks that where released a few years back. P&P has recently posted a Community Drop of the code refresh for the Mobility Block on the Codeplex and it includes the new block which is called ContainerModel. P&P has decided to utilize the Funq container that was developed by Daniel Cazzulino. So, I've taken this container and updated the sample for the MobileMVC to make a use of it.
Let's continue on the sample of how you can utilize the new features in the MobileMVC framework. I have modified the existing sample MVCDemoClient (a part of the download of the framework), so let's see how we'd initialize container with the views and controllers:
private static void Initialize()
container = new Container();
// Register Login view and controller
container.Register<LoginForm>(c => new LoginForm());
container.Register<LoginController>(c =>
new LoginController(c.Resolve<LoginForm>()))
.InitializedBy((c, v) => v.Container = c);
// Register Search view and controller
container.Register<SearchForm>(c => new SearchForm());
container.Register<SearchController>(c =>
new SearchController(c.Resolve<SearchForm>()))
container.Register<DetailForm>(c => new DetailForm());
container.Register<DetailController>(c =>
new DetailController(c.Resolve<DetailForm>()))
// Register data model
container.Register<Products>(c => new Products());
// Set ControllerProvider
Navigator.SetControllerProvider(new ControllerProvider(container));
In the code above when we register a controller, you can see that we call: .InitializedBy((c, v) => v.Container = c). This means that when an instance of the controller will be created we want to assign the same instance of the container to the Container property which I've added to the controller. We also make a call to the SetControllerProvider method and passing and instance of the ControllerProvider class which as you can guess implements IControllerProvider interface and makes use of the Container:
public class ControllerProvider : IControllerProvider
private Container container;
public ControllerProvider(Container container)
this.container = container;
#region IControllerProvider Members
public Controller GetController<T>()
return this.container.Resolve<T>() as Controller;
public Controller GetController<T>(IView view)
Controller controller = this.container.Resolve<Controller>();
controller.View = view;
return controller;
// … Other methods ommitted for brevity
#endregion
After this short preparation we can now modifiy our code to use the Navigator class. This is how we can show the SearchForm from the LoginController:
private void ShowSearchView()
//SearchController controller = new SearchController(new SearchForm());
//NavigationService.Navigate(controller);
this.Navigator.Navigate<SearchController>();
Ability to access the Container from the controller is also giving us much more separation from the Data Model or other services that you may use in the application. For example this is how we can get access to the Products data model in the SearchController:
// ViewLoaded event from the view
private void OnViewLoaded(object sender, EventArgs e)
// Show busy cursor
Cursor.Current = Cursors.WaitCursor;
// Get an instance from the container
Products products = this.Container.Resolve<Products>();
// Populate data
products.PopulateList();
// Assign the Model
this.view.ViewData.Model = products;
// Notify the view of the changes
this.NotifyView();
// Restore the cursor
Cursor.Current = Cursors.Default;
Overall, I think the usage of the container with the MVC pattern gives you much more flexibility when designing your applications. It allows you to decouple the access to the application services giving you more room during the unit testing as well as making changes to the application without breaking too many dependencies.
You can find the updated version of the MobileMVC framework and the sample in the downloads section of the codeplex project:
http://mobilemvc.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=26507
Check out the Rob's blog post in which he describes the technique that can help you to allocate less memory when creating managed applications on Windows Phones:
http://blogs.msdn.com/robtiffany/archive/2009/04/09/memmaker-for-the-net-compact-framework.aspx
Would you like to develop applications that utilize the bluetooth functionality on the WM emulator? Now you can. Check out this article on CodeProject:
http://www.codeproject.com/KB/mobile/bth4devemul.aspx
I've received a question from the customer the other day asking me how he can implement functionality of "dimming" background effect when a message box is shown in his Windows Mobile application. In fact it should be pretty easy to do utilizing the DrawAlpha method from the GraphicsExtender class that I showed you in this webcast. Take a look at the following code snippet:
protected override void OnPaint(PaintEventArgs e)
// Create a temp bitmap
Bitmap dimBackGround = new Bitmap(this.Width, this.Height);
Graphics gxTemp = Graphics.FromImage(dimBackGround);
// Color it black
gxTemp.Clear(Color.Black);
// Draw it with alpha transparency
e.Graphics.DrawAlpha(dimBackGround, 100, 0, 0);
// Clean up
gxTemp.Dispose();
dimBackGround.Dispose();
The code above shows OnPaint override method in the BackgroundForm class that I've added to the demo project. I've set the FormBorderStyle to None and WindowState to Maximized for this from to make it full screen.
So, now before displaying a message box you will need to show the BackroundForm:
BackgroundForm form = new BackgroundForm();
form.Show();
MessageBox.Show(txtMessage.Text);
form.Close();
And here's the result:
Download the sample code from here.
I will be participating in the TechDays next week on April 1st. It's a 24 hour virtual event with almost a hundred sessions that will be repeated for different time zones for people across the globe. I was asked to repeat the Creating Compelling and Attractive UIs for Windows Mobile Applications session. I am going to have two live sessions 10:30 pm GMT and 1:30 pm GMT. Chistopher Fairbairn will be presenting the same session in the Asia Pacific time zone.
Next week I am going to present a second part of the series on creating attractive UIs on Windows Mobile devices. This time I will show you how to customize built-in controls that come with .NET CF, such as TextBox, DataGrid, ListView etc...
You can register for the web cast here:
http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032408754&EventCategory=4&culture=en-US&CountryCode=US
UPDATE:
The code from the session is available for download from:
https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=uiframework&ReleaseId=2315