Building a Simple Windows Phone Dialer App
published on: 8/2/2011 | Views: N/A | Tags: MVVM Tasks
by Mike Gold![]()
Figure 1 - Phone Dialer App
Introduction
One thing Microsoft is good at is creating simple ways to make life painless for application developers. Along comes the Window's Phone 7 technology and it seems to get even easier. This Silverlight Application took me about 1/2 hour to write. Although there isn't a lot to it, you can use your imagination to create highly functional applications that can be distributed and sold in the app store. Even though this particular app won't be sold anytime soon, imagine what one could do given another hour of time! Unfortunately time is a commodity these days, but its still fun to write these phone apps.
The Design
The application design is fairly simple. There is only a MainPage and 2 view models: A MainPageViewModel and a ContactViewModel for each item on the page. The full design is shown in figure 2 below. The MainPage View contains an ItemsControl that binds to a list of ContactViewModels in the MainPageViewModel. The MainPageView has a DataTemplate that binds to the properties in the ContactViewModel. Inside the DataTemplate is a button whose content is bound to the name of the contact in the ContactViewModel. The button's command is bound to a RelayCommand in the ContactViewModel that dials the phone number of the contact. This application uses MVVM-Lite for the Windows Phone to take advantage of the RelayCommand as well as the ViewModelBase class for raising property changes.
Figure 2 - UML Application Design of Phone Dialer Reverse Engineered using WithClass 2010
The Code
In order to populate the ItemsControl, we need to populate the list of contacts in the ViewModel that is bound to the ItemsControl. In the MainPageViewModel, we take advantage of the built in Microsoft.Phone.UserData library that allows us to get the contacts through an asynchronous call to the phone. The MainPageViewModel is shown in listing 1. It searches the phone for the contacts in the constructor and in the callback, populates the collection of ContactViewModels with a LINQ expression. Since the ContactViewModels are bound to the View's ItemsControl, the list of buttons will show up on the phone after the callback populates the collection of contacts.
Listing 1- The MainPageViewModel
using System;
using System.Collections.ObjectModel;
using System.Linq;
using GalaSoft.MvvmLight;
using Microsoft.Phone.UserData;
namespace ContactsDialer.ViewModel
{
public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel()
{
var cons = new Contacts();
// hook up an event handler to retrieve the contacts after we've searched for them on the WP7
cons.SearchCompleted += ContactsSearchCompleted;
//Start the search asynchronously.
cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #1");
}
private void ContactsSearchCompleted(object sender, ContactsSearchEventArgs e)
{
// search is complete, add the contacts to ContactViewModels
PhoneContacts = new ObservableCollection<ContactViewModel>(e.Results.OrderBy(c => c.DisplayName).Select(
contact =>
new ContactViewModel {Name = contact.CompleteName.FirstName, Number = contact.PhoneNumbers.FirstOrDefault()}));
}
private ObservableCollection<ContactViewModel> _phoneContacts;
public ObservableCollection<ContactViewModel> PhoneContacts
{
get { return _phoneContacts; }
set { _phoneContacts = value;
RaisePropertyChanged("PhoneContacts");
}
}
}
}
When a User presses a button, it triggers the ICommand bound to the ContactViewModel. Listing 2 shows the contact view model that contains the individual's contact info. One thing that might be fun to add to this app is additional contact information since the Contact class has all the contact detail you've made available for a particular contact. Perhaps you could put the additional info in a small navigation button next to the contact button.
The DialContactCommand bound to the button uses the PhoneCallTask to dial the number for the contact. The PhoneCallTask won't actually dial the number, but it will prompt the user to dial so that all the user needs to do is confirm that they want to make the call.
Listing 2 - The ContactViewModel
using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Phone.Tasks;
using Microsoft.Phone.UserData;
namespace ContactsDialer.ViewModel
{
public class ContactViewModel : ViewModelBase
{
public ContactViewModel()
{
DialContactCommand = new RelayCommand<ContactPhoneNumber>(OnDialPhoneNumber);
}
private static void OnDialPhoneNumber(ContactPhoneNumber number)
{
// create the task with the contacts phone number
var task = new PhoneCallTask {PhoneNumber = number.PhoneNumber};
// prompt the user to dial the number
task.Show();
}
public RelayCommand<ContactPhoneNumber> DialContactCommand { get; private set; }
private string _name;
private ContactPhoneNumber _number;
public String Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
public ContactPhoneNumber Number
{
get { return _number; }
set
{
_number = value;
RaisePropertyChanged("Number");
}
}
}
}
The View
The MainPage is a fairly simple view with an ItemsControl and a DataTemplate to describe the items in the ItemsControl. The items, in this case, are buttons showing each of your contacts. Pressing a button dials the contacts number. The ItemsControl is bound to the MainPageViewModel in listing 1 and the ItemTemplate is bound to the ContactViewModel in listing 2.
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="ContactsDialer.MainPage"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.Resources>
<DataTemplate x:Key="contactTemplate">
<Button Content="{Binding Name}" Command="{Binding DialContactCommand}" CommandParameter="{Binding Number}" />
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="SIMPLE PHONE DIALER" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="List of Contacts" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ScrollViewer Height="350">
<ItemsControl ItemsSource="{Binding PhoneContacts}" ItemTemplate="{StaticResource contactTemplate}" HorizontalAlignment="Left" Margin="12,84,0,0" x:Name="listBox1" VerticalAlignment="Top" Width="424" />
</ScrollViewer>
</Grid>
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->
</phone:PhoneApplicationPage>
Conclusion
Building a simple phone dialer is a snap with the built in PhoneTask and Contact classes. You can play around with this application to create a speed dialer for your favorite contacts, or perhaps add drag and drop to sort your call tree priorities. Perhaps you can add a filter that allows you to show only buttons by contact location. If you put your mind to it, there is no telling how well you can make contact with your potential for useful apps on the Windows Phone using C# and .NET technology.
You can also follow us on Twitter @winphonegeek
|
|
About the author:
Mike is a Senior Software Developer in C# and .NET and has been developing Microsoft technology for 22 years. He was a Microsoft MVP for 3 years in Visual C# and has contributed over 200 publications and several books to the .NET community. He currently consults for WellMed in Austin, Texas. Mike is looking forward the possibilities with the Windows Phone. He can be reached at mike@microgold.com |
|
Senior .NET Developer |
|
Comments
modifying the call task
posted by: range152 on 12/4/2011 2:07:03 AM
hi there, this is a nice tutorial, but I am just wondering if there's anyway to disable the "confirm" dialog box? I want to be able to call straight away once i press that button...
Our Top Articles & Free books
- Our FREE e-book: "Windows Phone Toolkit In Depth" 2nd edition
- 400+ Windows Phone Development articles in our Article Index
- 21 WP7 Toolkit in Depth articles covering all controls
- 12 WP7 Coding4Fun Toolkit in Depth articles covering all controls
- Performance Tips when creating WP7 apps
- Creating a WP7 Custom Control in 7 Steps
- WP7 working with VisualStates: How to make a ToggleSwitch from CheckBox
- What makes a WP7 App successful
- Creating theme friendly UI in WP7 using OpacityMask
- Implementing Windows Phone 7 DataTemplateSelector and CustomDataTemplateSelector
- All about Splash Screens in WP7 – Creating animated Splash Screen
- Getting Started with Unit Testing in Silverlight for WP7
- WP7 WatermarkedTextBox custom control
Our Top Tips & Samples
- All about WP7 Isolated Storage series
- WP7 Dynamically Generating DataTemplate in code
- 5 tips for a successful WP7 Marketplace submission
- WP7: Navigating to a page in different assembly
- WP7 ContextMenu: answers to popular questions
- WP7 ListBox: answers to popular questions
- WP7 working with Images: Content vs Resource build action
- WP7 Element Binding samples
- WP7 working with XML: reading, filtering and databinding
- Drawing in WP7: #2 Drawing shapes with finger
- WP7 TextBox Light theme problems - the solution
- Changing the WP7 Panorama Background Image dynamically with Animation
