参考改版后的:http://blog.csdn.net/oneonce/article/details/77072894
有点问题:背景设置不生效,目前只能用白色(默认)背景,求指点
public class ImageTextBox : TextBox
{
private const double PLACEHOLDER_FONTSIZE_DEF = 10.0;
private const double NUMERATOR = 1.0;
private const double DENOMINATOR = 5.0;
private const double IMAGE_MARGIN_LEFT = 3.0;
private const double IMAGE_MARGIN_RATE= -NUMERATOR / DENOMINATOR;
private const double IMAGE_MARGIN_TOP = 3.0;
private const double IMAGE_MARGIN_BOTTOM = 3.0;
private const double IMAGE_MARGIN_RIGHT = 3.0;
private const double IMAGE_MARGIN_TEXT = 2.0;
private const double CORNER_RADIUS = 0.0;
private TextBox mInputBox = null;
private Thickness mInputBoxMargin = new Thickness(0, IMAGE_MARGIN_TOP, 0 , IMAGE_MARGIN_BOTTOM);
private double mInputBoxWidth = 0.0;
private Thickness mLeftImageMargin = new Thickness(CORNER_RADIUS * (1 + IMAGE_MARGIN_LEFT), IMAGE_MARGIN_TOP, IMAGE_MARGIN_TEXT, IMAGE_MARGIN_BOTTOM);
private Size mLeftImageSize = new Size(0, 0);
private double mPlaceHolderFontSize = PLACEHOLDER_FONTSIZE_DEF;
static ImageTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageTextBox), new FrameworkPropertyMetadata(typeof(ImageTextBox)));
}
public ImageTextBox()
{
}
public override void OnApplyTemplate()
{
mInputBox = GetTemplateChild("TEXTBOX_PART") as TextBox;
base.OnApplyTemplate();
}
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(nameof(Image), typeof(ImageSource), typeof(ImageTextBox),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public static readonly DependencyProperty PlaceHolderProperty = DependencyProperty.Register(nameof(PlaceHolder), typeof(string), typeof(ImageTextBox), new PropertyMetadata(""));
public string PlaceHolder
{
get { return (string)GetValue(PlaceHolderProperty); }
set { SetValue(PlaceHolderProperty, value); }
}
public double PlaceHolderFontSize
{
get {
if (PLACEHOLDER_FONTSIZE_DEF == mPlaceHolderFontSize)
{
mPlaceHolderFontSize = FontSize * 3.0 / 5.0;
}
return mPlaceHolderFontSize;
}
}
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(nameof(CornerRadius), typeof(string), typeof(ImageTextBox), new PropertyMetadata(CORNER_RADIUS.ToString()));
public string CornerRadius
{
get { return (string)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
//public static readonly DependencyProperty InputBoxMarginProperty = DependencyProperty.Register(nameof(InputBoxMargin), typeof(Thickness), typeof(ImageTextBox), new PropertyMetadata(new Thickness(0, 0, 0, 0)));
public Thickness InputBoxMargin
{
//get { return (Thickness)GetValue(InputBoxMarginProperty); }
//set { SetValue(InputBoxMarginProperty, value); }
get
{
double cornerRadius = double.Parse(CornerRadius);
double lr= cornerRadius * (1 + IMAGE_MARGIN_RATE);
if (0 == mInputBoxMargin.Left)
{
if (0 == cornerRadius)
{
mInputBoxMargin.Left = IMAGE_MARGIN_LEFT;
}
else
{
mInputBoxMargin.Left = lr;
}
}
if (0 == mInputBoxMargin.Right)
{
if (0 == cornerRadius)
{
mInputBoxMargin.Right = IMAGE_MARGIN_RIGHT;
}
else
{
mInputBoxMargin.Right = lr;
}
}
return mInputBoxMargin;
}
}
public double InputBoxWidth
{
get
{
double cornerRadius = double.Parse(CornerRadius);
double lr = cornerRadius * (1 + IMAGE_MARGIN_RATE);
if (double.IsNaN(Width))
{
mInputBoxWidth = 10;
}
else
{
if (0 == mInputBoxWidth)
{
mInputBoxWidth = Width - 2 *lr;
}
}
return mInputBoxWidth;
}
}
public Thickness LeftImageMargin
{
get
{
return mLeftImageMargin;
}
}
public Size LeftImageSize
{
get
{
return mLeftImageSize;
}
}
private static void ImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ImageTextBox thisImageTextBox = null;
ImageSource imageSource = null;
if (null != sender)
{
thisImageTextBox = sender as ImageTextBox;
if (null == thisImageTextBox)
{
return;
}
}
if (e.NewValue is ImageSource)
{
imageSource = e.NewValue as ImageSource;
if (null == imageSource)
{
return;
}
}
double cornerRadius = double.Parse((string)thisImageTextBox.GetValue(CornerRadiusProperty));
if (0 == cornerRadius)
{
thisImageTextBox.mLeftImageMargin.Left = IMAGE_MARGIN_LEFT;
}
else
{
thisImageTextBox.mLeftImageMargin.Left = cornerRadius * (1 + IMAGE_MARGIN_RATE);
thisImageTextBox.mInputBoxMargin.Right = cornerRadius * (1 + IMAGE_MARGIN_RATE) + IMAGE_MARGIN_TEXT;
}
if (0 == thisImageTextBox.mInputBoxMargin.Left)
{
thisImageTextBox.mInputBoxMargin.Left = thisImageTextBox.mLeftImageMargin.Left + imageSource.Width + thisImageTextBox.mLeftImageMargin.Right;
}
thisImageTextBox.mInputBoxWidth = thisImageTextBox.Width - thisImageTextBox.mInputBoxMargin.Left - thisImageTextBox.mInputBoxMargin.Right ;
thisImageTextBox.mLeftImageSize.Width = imageSource.Width;
thisImageTextBox.mLeftImageSize.Height = imageSource.Height;
}
}
<Style TargetType="{x:Type ctrls:ImageTextBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="#ff2D2D30"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="CaretBrush" Value="Black"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctrls:ImageTextBox}">
<Grid x:Name="ROOT_PART" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border x:Name="mask"
Opacity="{TemplateBinding Opacity}"
Background="White"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}}" />
<Border/>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Panel.ZIndex="2"
Margin="{Binding LeftImageMargin, RelativeSource={RelativeSource TemplatedParent}}"
Width="{Binding LeftImageSize.Width, RelativeSource={RelativeSource TemplatedParent}}"
Height="{Binding LeftImageSize.Height, RelativeSource={RelativeSource TemplatedParent}}"
Source="{Binding Image, RelativeSource={RelativeSource TemplatedParent}}"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBox x:Name="TEXTBOX_PART" Panel.ZIndex="1"
Foreground="{TemplateBinding Foreground}"
RenderOptions.ClearTypeHint="Enabled"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Width="{Binding InputBoxWidth, RelativeSource={RelativeSource TemplatedParent}}"
Margin="{Binding InputBoxMargin, RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{TemplateBinding FontSize}"
BorderThickness="0"
VerticalContentAlignment="Center"
TextAlignment="{TemplateBinding TextAlignment}"
CaretBrush="{Binding CaretBrush, RelativeSource={RelativeSource AncestorType={x:Type ctrls:ImageTextBox}}}"
ToolTip="{TemplateBinding ToolTip}"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Resources>
<VisualBrush x:Key="PLACEHOLDER_PART" TileMode="None" Opacity="1" Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBox Opacity="1" Foreground="LightGray"
Text="{Binding Path=PlaceHolder, RelativeSource={RelativeSource AncestorType={x:Type ctrls:ImageTextBox}}}"
Background="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{Binding PlaceHolderFontSize, RelativeSource={RelativeSource AncestorType={x:Type ctrls:ImageTextBox}}}"
Margin="{Binding InputBoxMargin, RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="0" BorderBrush="Transparent"
Width="{Binding Width, ElementName=TEXTBOX_PART}"/>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Resources>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource PLACEHOLDER_PART}"/>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="{StaticResource PLACEHOLDER_PART}"/>
</Trigger>
<!--<DataTrigger Binding="{Binding Path=Text,RelativeSource={RelativeSource AncestorType={x:Type TextBox}},Converter={StaticResource isNullConverter},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>-->
<!--<Trigger Property="IsFocused" Value="False">
<Setter Property="Background" Value="Transparent" />
</Trigger>-->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Text.Length}" Value="0">
<Setter Property="Background" Value="{StaticResource PLACEHOLDER_PART}"/>
</DataTrigger>
<!--<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},Path=Text.Length}" Value="0"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},Path=IsFocused}" Value="False"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="{StaticResource PLACEHOLDER_PART}"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>-->
<!--<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Background" Value="Transparent" />
</Trigger>-->
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用1:
<ctrls:ImageTextBox x:Name="tbUserName" Width="300" Height="50"
PlaceHolder="请输入用户名"
TextChanged="tbUserName_TextChanged"/>
使用2:
<ctrls:ImageTextBox x:Name="tbUserName" Width="300" Height="50"
CornerRadius="20"
PlaceHolder="请输入用户名"
TextChanged="tbUserName_TextChanged"/>
使用3:
<ctrls:ImageTextBox x:Name="tbUserName" Width="300" Height="50"
PlaceHolder="请输入用户名"
Image="Resources/Images/logo.jpg"
TextChanged="tbUserName_TextChanged"/>
使用4:
<ctrls:ImageTextBox x:Name="tbUserName" Width="300" Height="50"
CornerRadius="20"
PlaceHolder="请输入用户名"
Image="Resources/Images/logo.jpg"
TextChanged="tbUserName_TextChanged"/>