Reputation: 1561
I want to make a custom TextBox
using XAML and a custom class with an additional property to TextBox called PosType
. PosType
will be rendered inside the red triangle in the side.
The TextBox
should be an ordinary textbox with enough margin from left to not intercept the other text.
Here is the Image showing the desired look of the textbox.
The Control class :
public class PosTextBox : TextBox
{
public string PosType { get; set; }
}
**The style I wrote : (quite similar approach to what I want except here I used border and other parts may not be accurate. **
xmlns:Pro="clr-namespace:Prox.XamlControls">
<!-- Custom TextBox -->
<Style x:Key="c1PosTextBox" TargetType="{x:Type Pro:PosTextBox}" >
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Pro:PosTextBox}">
<Grid>
<Border>
<Border>
<TextBlock Text ="{TemplateBinding Path= Pro:PosType}"></TextBlock>
<!--<TextBlock Text ="{TemplateBinding ElementName=Pro:PosTextBox, Path= Pro:PosType}"></TextBlock>-->
</Border>
</Border>
<Border Margin="5,10,5,10">
<ContentPresenter Name="Content" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" TextBlock.Foreground="White"></ContentPresenter>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How to create this custom textbox and achieve the desired look?
Edit: Please guide me to fix the minor issues based on the same approach I mentioned above.
Upvotes: 1
Views: 10615
Reputation: 6547
You could do that using Adorners
Adorners are rendered in a different layer called AdornerLayer
on top of the UIElement
, Which can get you the desired affect.
public class PosTypeAdorner : Adorner
{
private string _posText;
// Be sure to call the base class constructor.
public PosTypeAdorner (UIElement adornedElement, string posText) : base(adornedElement)
{
_posText = posText;
}
// A common way to implement an adorner's rendering behavior is to override the OnRender
// method, which is called by the layout system as part of a rendering pass.
protected override void OnRender(DrawingContext drawingContext)
{
// Draw the red triangle with it's text using the drawingContext here
}
}
Assuming you want the text of the PosType
to be bindable, you should make it as a Dependency property
.
Use OnApplyTemplate
to attach the adorner to your text box
public class PosTextBox : TextBox
{
public PosTextBox()
{
}
public static readonly DependencyProperty PosTypeProperty =
DependencyProperty.Register("PosType", typeof (string), typeof (PosTextBox), new PropertyMetadata(default(string)));
public string PosType
{
get { return (string)GetValue(PosTypeProperty); }
set { SetValue(PosTypeProperty, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var layer = AdornerLayer.GetAdornerLayer(this);
var posAdorner = new PosTypeAdorner(this, PosType);
layer.Add(posAdorner);
}
}
For more information, you can check out this links:
http://www.codeproject.com/Articles/54472/Defining-WPF-Adorners-in-XAML
http://www.nbdtech.com/Blog/archive/2010/06/21/wpf-adorners-part-1-ndash-what-are-adorners.aspx
Good luck
Upvotes: 4