C#
Empezamos creamos una clase que extienda de Control con la siguiente definición:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace CustomTextBox.Controls
{
public class PhoneTextBox : Control
{
#region Members
private TextBlock _hintTextBlock;
private TextBox _controlTextBox;
#endregion Members
#region DependencyProperties
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(PhoneTextBox), new PropertyMetadata(null));
public string Hint
{
get { return (string)GetValue(HintProperty); }
set { SetValue(HintProperty, value); }
}
public static readonly DependencyProperty HintProperty =
DependencyProperty.Register("Hint", typeof(string), typeof(PhoneTextBox), new PropertyMetadata(null));
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(PhoneTextBox), new PropertyMetadata(string.Empty));
#endregion DependencyProperties
public PhoneTextBox()
{
DefaultStyleKey = typeof(PhoneTextBox);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this._hintTextBlock = (TextBlock)GetTemplateChild("HintTextBlock");
this._controlTextBox = (TextBox)GetTemplateChild("ControlTextBox");
}
protected override void OnKeyUp(System.Windows.Input.KeyEventArgs e)
{
base.OnKeyUp(e);
this._hintTextBlock.Visibility = string.IsNullOrWhiteSpace(this._controlTextBox.Text) ? Visibility.Visible : Visibility.Collapsed;
}
}
}
Y un Converter:
using System;
using System.Windows;
using System.Windows.Data;
namespace CustomTextBox.Converters
{
public class ObjectToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null != value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
XAML
Y continuamos definiendo la plantilla del control que acabamos de crear mediante un estilo implícito de la siguiente manera:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:CustomTextBox.Controls"
xmlns:converters="clr-namespace:CustomTextBox.Converters">
<converters:ObjectToVisibilityConverter x:Key="ObjectToVisibilityConverter"/>
<Style TargetType="controls:PhoneTextBox">
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:PhoneTextBox">
<Border Background="{TemplateBinding Background}" CornerRadius="5" Margin="{StaticResource PhoneTouchTargetOverhang}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Margin="6" Source="{TemplateBinding ImageSource}" Width="32" Height="32" VerticalAlignment="Center" Visibility="{Binding ImageSource, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource ObjectToVisibilityConverter}}"/>
<TextBlock Margin="6" x:Name="HintTextBlock" Grid.Column="1" Text="{TemplateBinding Hint}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" Opacity="0.54" />
<TextBox Margin="6" x:Name="ControlTextBox" Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" >
<TextBox.Template>
<ControlTemplate TargetType="TextBox">
<ContentControl x:Name="ContentElement" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
</ControlTemplate>
</TextBox.Template>
</TextBox>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Uso
Agregar el namespace de PhoneTextBox a la página o al control correspondiente:
<phone:PhoneApplicationPage
x:Class="CustomTextBox.MainPage"
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"
mc:Ignorable="d"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
xmlns:controls="clr-namespace:CustomTextBox.Controls">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="WWW.REACHSOS.COM" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="xaml development" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<controls:PhoneTextBox Hint="efectivamente es el joven" Background="White" Foreground="Blue" ImageSource="/Assets/icon.png"/>
<controls:PhoneTextBox Grid.Row="1" Hint="y dile que ahorita no" Background="Brown" Foreground="White" ImageSource="/Assets/icon.png"/>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
CodePlex
Código fuente disponible en: Windows Phone -> CustomTextBox