ProfileItem control for WP7
In the number of the applications that I'd worked on I had to create a screen to display information about a person such as phone, address, email etc... So the screen essentially'd look like the as profile in the people hub:
So I have created the contro to save a burden of implementing the functionality again and again and called it ProfileItem. Besides displaying the text "call mobile" for example and a phone number I wanted for this control to also support MVVM commanding that would react on when a control is clicked, therefore it'd implement Command property. This is how the XAML for the control looks like:
<UserControl x:Class="ProfileItemTest.Controls.ProfileItem"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
>
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Name="textBlockTitle" Grid.Row="0" HorizontalAlignment="Left"
Style="{StaticResource PhoneTextExtraLargeStyle}" Text="engagement" />
<TextBlock Name="textBlockValue" Grid.Row="1" HorizontalAlignment="Left" Margin="14,-6,0,6"
TextWrapping="Wrap" Text="(none)" FontSize="22" />
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener x:Name="listener"
Tap="OnTap"/>
</toolkit:GestureService.GestureListener>
</Grid>
</Grid>
</UserControl>
And the code behind:
public partial class ProfileItem : UserControl
{
private event EventHandler Click;
public ProfileItem()
{
InitializeComponent();
this.Click += (sender, e) =>
{
if (Command != null && Command.CanExecute(CommandParameter))
Command.Execute(CommandParameter);
};
this.Loaded += new RoutedEventHandler(ProfileItem_Loaded);
}
void ProfileItem_Loaded(object sender, RoutedEventArgs e)
{
if (this.Command != null)
{
textBlockValue.Foreground = (Brush)Application.Current.Resources["PhoneAccentBrush"];
}
}
#region ICommand
public static DependencyProperty CommandProperty =
DependencyProperty.Register("Command",
typeof(ICommand), typeof(ProfileItem),
new PropertyMetadata(null, CommandChanged));
private static void CommandChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
{
var button = source as ProfileItem;
if (button == null) return;
button.RegisterCommand(args.OldValue as ICommand, args.NewValue as ICommand);
}
private void RegisterCommand(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null)
oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;
if (newCommand != null)
newCommand.CanExecuteChanged += HandleCanExecuteChanged;
HandleCanExecuteChanged(newCommand, EventArgs.Empty);
}
private void HandleCanExecuteChanged(object sender, EventArgs args)
{
if (Command != null)
IsEnabled = Command.CanExecute(CommandParameter);
}
public ICommand Command
{
get { return GetValue(CommandProperty) as ICommand; }
set { SetValue(CommandProperty, value); }
}
public static DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter",
typeof(object), typeof(ProfileItem),
new PropertyMetadata(null));
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
#endregion
public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached("Title", typeof(string), typeof(ProfileItem), new PropertyMetadata(OnTitleValueChanged));
public string Title
{
get
{
return (string)base.GetValue(TitleProperty);
}
set
{
base.SetValue(TitleProperty, value);
}
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(string), typeof(ProfileItem), new PropertyMetadata(OnValueChanged));
public string Value
{
get
{
return (string)base.GetValue(ValueProperty);
}
set
{
base.SetValue(ValueProperty, value);
}
}
private static void OnTitleValueChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
ProfileItem item = (ProfileItem)target;
item.textBlockTitle.Text = (string)args.NewValue;
}
private static void OnValueChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
ProfileItem item = (ProfileItem)target;
item.textBlockValue.Text = (string)args.NewValue;
}
private void OnTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
{
if (this.Click != null)
{
this.Click(this, EventArgs.Empty);
}
}
private class ClickCommandBinding
{
private readonly ICommand command;
private readonly ProfileItem button;
private readonly Func<object> parameterGetter;
/// <summary>
///
/// </summary>
/// <param name="iconButton"></param>
/// <param name="command"></param>
/// <param name="parameterGetter"></param>
public ClickCommandBinding(ProfileItem button, ICommand command, Func<object> parameterGetter)
{
this.command = command;
this.button = button;
this.parameterGetter = parameterGetter;
this.button.IsEnabled = this.command.CanExecute(parameterGetter());
this.command.CanExecuteChanged += this.CommandCanExecuteChanged;
this.button.listener.Tap += this.ButtonClicked;
}
public void Detach()
{
this.button.MouseLeftButtonDown -= this.ButtonClicked;
this.command.CanExecuteChanged -= this.CommandCanExecuteChanged;
}
private void ButtonClicked(object s, EventArgs e)
{
this.command.Execute(this.parameterGetter());
}
private void CommandCanExecuteChanged(object s, EventArgs ea)
{
this.button.IsEnabled = this.command.CanExecute(this.parameterGetter());
}
}
}
I've also created a sample that would display a contact data on your phone. This is how the screen looks like in the sample:
You can download the code for the control and the sample from here.