Freigeben über


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.

 

ProfileItemTest.zip