Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das folgende Beispiel zeigt, wie Platzhaltertext in einem TextBox angezeigt wird, wenn das TextBox
leer ist. Wenn der TextBox
Text enthält, wird der Platzhaltertext ausgeblendet. Der Platzhaltertext hilft Benutzern zu verstehen, welche Art von Eingabe der TextBox
erwartet.
In diesem Artikel erfahren Sie, wie Sie Folgendes tun:
- Erstellen Sie eine angefügte Eigenschaft, um den Platzhaltertext bereitzustellen.
- Erstellen Sie einen Zierer, um den Platzhaltertext anzuzeigen.
- Fügen Sie die zugeordnete Eigenschaft zu einem TextBox Steuerelement hinzu.
Erstellen einer angefügten Eigenschaft
Mit angefügten Eigenschaften können Sie Werte an ein Steuerelement anfügen. Sie verwenden dieses Feature in WPF häufig, z. B. wenn Sie Grid.Row
oder Panel.ZIndex
Eigenschaften an einem Steuerelement festlegen. Weitere Informationen finden Sie unter "Übersicht über angefügte Eigenschaften". In diesem Beispiel werden angefügte Eigenschaften genutzt, um Platzhaltertext zu einem TextBox hinzuzufügen.
Fügen Sie ihrem Projekt eine neue Klasse mit dem Namen
TextBoxHelper
hinzu, und öffnen Sie sie.Fügen Sie die folgenden Namespaces hinzu:
using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media;
Imports System.Linq Imports System.Security.Cryptography Imports System.Windows Imports System.Windows.Controls Imports System.Windows.Documents Imports System.Windows.Media
Erstellen Sie eine neue Abhängigkeitseigenschaft namens
Placeholder
.Diese Abhängigkeitseigenschaft verwendet den Rückrufdelegaten für Eigenschaftsänderungen.
public static string GetPlaceholder(DependencyObject obj) => (string)obj.GetValue(PlaceholderProperty); public static void SetPlaceholder(DependencyObject obj, string value) => obj.SetValue(PlaceholderProperty, value); public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached( "Placeholder", typeof(string), typeof(TextBoxHelper), new FrameworkPropertyMetadata( defaultValue: null, propertyChangedCallback: OnPlaceholderChanged) );
Public Shared Function GetPlaceholder(obj As DependencyObject) As String Return obj.GetValue(PlaceholderProperty) End Function Public Shared Sub SetPlaceholder(obj As DependencyObject, value As String) obj.SetValue(PlaceholderProperty, value) End Sub Public Shared ReadOnly PlaceholderProperty As DependencyProperty = DependencyProperty.RegisterAttached( "Placeholder", GetType(String), GetType(TextBoxHelper), New FrameworkPropertyMetadata( defaultValue:=Nothing, propertyChangedCallback:=AddressOf OnPlaceholderChanged) )
Erstellen Sie die
OnPlaceholderChanged
-Methode, um die angefügte Eigenschaft mit einemTextBox
zu integrieren.private static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is TextBox textBoxControl) { if (!textBoxControl.IsLoaded) { // Ensure that the events are not added multiple times textBoxControl.Loaded -= TextBoxControl_Loaded; textBoxControl.Loaded += TextBoxControl_Loaded; } textBoxControl.TextChanged -= TextBoxControl_TextChanged; textBoxControl.TextChanged += TextBoxControl_TextChanged; // If the adorner exists, invalidate it to draw the current text if (GetOrCreateAdorner(textBoxControl, out PlaceholderAdorner adorner)) adorner.InvalidateVisual(); } }
Private Shared Sub OnPlaceholderChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs) Dim textBoxControl = TryCast(d, TextBox) If textBoxControl IsNot Nothing Then If Not textBoxControl.IsLoaded Then 'Ensure that the events are not added multiple times RemoveHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded AddHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded End If RemoveHandler textBoxControl.TextChanged, AddressOf TextBoxControl_TextChanged AddHandler textBoxControl.TextChanged, AddressOf TextBoxControl_TextChanged 'If the adorner exists, invalidate it to draw the current text Dim adorner As PlaceholderAdorner = Nothing If GetOrCreateAdorner(textBoxControl, adorner) Then adorner.InvalidateVisual() End If End If End Sub
Es gibt zwei Möglichkeiten, wie diese Methode aufgerufen wird, wenn sich der Wert der angefügten Eigenschaft ändert:
- Wenn die angefügte Eigenschaft zum ersten Mal einer
TextBox
hinzugefügt wird, wird diese Methode aufgerufen. Diese Aktion bietet die Möglichkeit, dass die angefügte Eigenschaft in die Ereignisse des Steuerelements integriert werden kann. - Immer wenn diese Eigenschaft geändert wird, kann die Verzierung ungültig gemacht werden, um den visuellen Platzhaltertext zu aktualisieren.
Die
GetOrCreateAdorner
Methode wird im nächsten Abschnitt erstellt.- Wenn die angefügte Eigenschaft zum ersten Mal einer
Erstellen Sie die Ereignishandler für die
TextBox
.private static void TextBoxControl_Loaded(object sender, RoutedEventArgs e) { if (sender is TextBox textBoxControl) { textBoxControl.Loaded -= TextBoxControl_Loaded; GetOrCreateAdorner(textBoxControl, out _); } } private static void TextBoxControl_TextChanged(object sender, TextChangedEventArgs e) { if (sender is TextBox textBoxControl && GetOrCreateAdorner(textBoxControl, out PlaceholderAdorner adorner)) { // Control has text. Hide the adorner. if (textBoxControl.Text.Length > 0) adorner.Visibility = Visibility.Hidden; // Control has no text. Show the adorner. else adorner.Visibility = Visibility.Visible; } }
Private Shared Sub TextBoxControl_Loaded(sender As Object, e As RoutedEventArgs) Dim textBoxControl As TextBox = TryCast(sender, TextBox) If textBoxControl IsNot Nothing Then RemoveHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded GetOrCreateAdorner(textBoxControl, Nothing) End If End Sub Private Shared Sub TextBoxControl_TextChanged(sender As Object, e As TextChangedEventArgs) Dim textBoxControl As TextBox = TryCast(sender, TextBox) Dim adorner As PlaceholderAdorner = Nothing If textBoxControl IsNot Nothing AndAlso GetOrCreateAdorner(textBoxControl, adorner) Then If textBoxControl.Text.Length > 0 Then 'Control has text. Hide the adorner. adorner.Visibility = Visibility.Hidden Else 'Control has no text. Show the adorner. adorner.Visibility = Visibility.Visible End If End If End Sub
Das Loaded Ereignis wird behandelt, sodass der Adorner erstellt werden kann, nachdem die Vorlage des Steuerelements angewendet wurde. Der Handler entfernt sich, nachdem das Ereignis ausgelöst wurde, und der Zierer wird erstellt.
Das TextChanged Ereignis wird behandelt, um sicherzustellen, dass der Zierer ausgeblendet oder angezeigt wird, je nachdem, ob der Text Wert auf einen Wert festgelegt ist.
Erstellen eines Zierers
Dies Adorner ist ein visuelles Element, das an ein Steuerelement gebunden und in einem AdornerLayer. Weitere Informationen finden Sie unter Übersicht über Adorner.
Öffnen Sie die
TextBoxHelper
Klasse.Fügen Sie den folgenden Code hinzu, um die
GetOrCreateAdorner
Methode zu erstellen.private static bool GetOrCreateAdorner(TextBox textBoxControl, out PlaceholderAdorner adorner) { // Get the adorner layer AdornerLayer layer = AdornerLayer.GetAdornerLayer(textBoxControl); // If null, it doesn't exist or the control's template isn't loaded if (layer == null) { adorner = null; return false; } // Layer exists, try to find the adorner adorner = layer.GetAdorners(textBoxControl)?.OfType<PlaceholderAdorner>().FirstOrDefault(); // Adorner never added to control, so add it if (adorner == null) { adorner = new PlaceholderAdorner(textBoxControl); layer.Add(adorner); } return true; }
Private Shared Function GetOrCreateAdorner(textBoxControl As TextBox, ByRef adorner As PlaceholderAdorner) As Boolean 'Get the adorner layer Dim layer As AdornerLayer = AdornerLayer.GetAdornerLayer(textBoxControl) 'If nothing, it doesn't exist or the control's template isn't loaded If layer Is Nothing Then adorner = Nothing Return False End If 'Layer exists, try to find the adorner adorner = layer.GetAdorners(textBoxControl)?.OfType(Of PlaceholderAdorner)().FirstOrDefault() 'Adorner never added to control, so add it If adorner Is Nothing Then adorner = New PlaceholderAdorner(textBoxControl) layer.Add(adorner) End If Return True End Function
Diese Methode bietet eine sichere Möglichkeit zum Hinzufügen oder Abrufen der Adorner. Schmuckstücke erfordern zusätzliche Sicherheit, da sie der Steuerung AdornerLayer hinzugefügt werden, die möglicherweise nicht vorhanden ist. Wenn eine angefügte XAML-Eigenschaft auf ein Steuerelement angewendet wird, wurde die Vorlage des Steuerelements noch nicht angewendet, um die visuelle Struktur zu erstellen, sodass die Verziererebene nicht vorhanden ist. Die Adornerschicht muss nach dem Laden des Steuerelements abgerufen werden. Möglicherweise fehlt die Verziererebene auch, wenn eine Vorlage, die die Verziererebene auslässt, auf das Steuerelement angewendet wird.
Fügen Sie der Klasse eine untergeordnete Klasse hinzu, die
PlaceholderAdorner
benannt istTextBoxHelper
.public class PlaceholderAdorner : Adorner { public PlaceholderAdorner(TextBox textBox) : base(textBox) { } protected override void OnRender(DrawingContext drawingContext) { TextBox textBoxControl = (TextBox)AdornedElement; string placeholderValue = TextBoxHelper.GetPlaceholder(textBoxControl); if (string.IsNullOrEmpty(placeholderValue)) return; // Create the formatted text object FormattedText text = new FormattedText( placeholderValue, System.Globalization.CultureInfo.CurrentCulture, textBoxControl.FlowDirection, new Typeface(textBoxControl.FontFamily, textBoxControl.FontStyle, textBoxControl.FontWeight, textBoxControl.FontStretch), textBoxControl.FontSize, SystemColors.InactiveCaptionBrush, VisualTreeHelper.GetDpi(textBoxControl).PixelsPerDip); text.MaxTextWidth = System.Math.Max(textBoxControl.ActualWidth - textBoxControl.Padding.Left - textBoxControl.Padding.Right, 10); text.MaxTextHeight = System.Math.Max(textBoxControl.ActualHeight, 10); // Render based on padding of the control, to try and match where the textbox places text Point renderingOffset = new Point(textBoxControl.Padding.Left, textBoxControl.Padding.Top); // Template contains the content part; adjust sizes to try and align the text if (textBoxControl.Template.FindName("PART_ContentHost", textBoxControl) is FrameworkElement part) { Point partPosition = part.TransformToAncestor(textBoxControl).Transform(new Point(0, 0)); renderingOffset.X += partPosition.X; renderingOffset.Y += partPosition.Y; text.MaxTextWidth = System.Math.Max(part.ActualWidth - renderingOffset.X, 10); text.MaxTextHeight = System.Math.Max(part.ActualHeight, 10); } // Draw the text drawingContext.DrawText(text, renderingOffset); } }
Public Class PlaceholderAdorner Inherits Adorner Public Sub New(adornedElement As UIElement) MyBase.New(adornedElement) End Sub Protected Overrides Sub OnRender(drawingContext As DrawingContext) Dim textBoxControl As TextBox = DirectCast(AdornedElement, TextBox) Dim placeholderValue As String = TextBoxHelper.GetPlaceholder(textBoxControl) If String.IsNullOrEmpty(placeholderValue) Then Return End If 'Create the formatted text object Dim text As New FormattedText( placeholderValue, System.Globalization.CultureInfo.CurrentCulture, textBoxControl.FlowDirection, New Typeface(textBoxControl.FontFamily, textBoxControl.FontStyle, textBoxControl.FontWeight, textBoxControl.FontStretch), textBoxControl.FontSize, SystemColors.InactiveCaptionBrush, VisualTreeHelper.GetDpi(textBoxControl).PixelsPerDip) text.MaxTextWidth = Math.Max(textBoxControl.ActualWidth - textBoxControl.Padding.Left - textBoxControl.Padding.Right, 10) text.MaxTextHeight = Math.Max(textBoxControl.ActualHeight, 10) 'Render based on padding of the control, to try and match where the textbox places text Dim renderingOffset As New Point(textBoxControl.Padding.Left, textBoxControl.Padding.Top) 'Template contains the content part; adjust sizes to try and align the text Dim part As FrameworkElement = TryCast(textBoxControl.Template.FindName("PART_ContentHost", textBoxControl), FrameworkElement) If part IsNot Nothing Then Dim partPosition As Point = part.TransformToAncestor(textBoxControl).Transform(New Point(0, 0)) renderingOffset.X += partPosition.X renderingOffset.Y += partPosition.Y text.MaxTextWidth = Math.Max(part.ActualWidth - renderingOffset.X, 10) text.MaxTextHeight = Math.Max(part.ActualHeight, 10) End If ' Draw the text drawingContext.DrawText(text, renderingOffset) End Sub End Class
Ein Verzierer erbt von der Adorner Klasse. Dieser spezielle Zierer setzt die OnRender(DrawingContext) Methode außer Kraft, um den Platzhaltertext zu zeichnen. Lassen Sie uns den Code aufschlüsseln:
- Überprüfen Sie zunächst, ob der Platzhaltertext durch Aufrufen
TextBoxHelper.GetPlaceholder(textBoxControl)
vorhanden ist. - Erstellen eines FormattedText-Objekts Dieses Objekt enthält alle Informationen darüber, welcher Text auf dem visuellen Element gezeichnet wird.
- Beide die FormattedText.MaxTextWidth- und FormattedText.MaxTextHeight-Eigenschaften werden auf den Bereich des Steuerelements festgelegt. Außerdem wird ein Mindestwert von 10 festgelegt, um sicherzustellen, dass das
FormattedText
Objekt gültig ist. - Die
renderingOffset
Position des gezeichneten Texts wird gespeichert. - Verwenden Sie die
PART_ContentHost
Vorlage "If", um es zu deklarieren. Dieser Teil stellt dar, wo der Text in der Vorlage des Steuerelements dargestellt wird. Wenn dieser Teil gefunden wird, passen SierenderingOffset
an, damit seine Position berücksichtigt wird. - Zeichnen Sie den Text, indem Sie DrawText(FormattedText, Point) aufrufen und das
FormattedText
Objekt sowie die Position des Textes übergeben.
- Überprüfen Sie zunächst, ob der Platzhaltertext durch Aufrufen
Anwenden der angefügten Eigenschaft
Nachdem die angefügte Eigenschaft definiert wurde, muss der Namespace in das XAML importiert und dann in einem TextBox Steuerelement referenziert werden. Der folgende Code ordnet den .NET-Namespace dem XML-Namespace DotnetDocsSample
l
zu.
<Window x:Class="DotnetDocsSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:DotnetDocsSample"
Title="Recipe Tracker" Width="400" SizeToContent="Height">
<StackPanel Margin="10">
<TextBlock FontSize="20" TextWrapping="Wrap">Welcome to Recipe Tracker! To get started, create a new account.</TextBlock>
<Label Padding="0,5">Name</Label>
<TextBox l:TextBoxHelper.Placeholder="Ex. Jeffry Goh" />
<Label Padding="0,5">Email</Label>
<TextBox l:TextBoxHelper.Placeholder="jeffry@contoso.com" />
<Label Padding="0,5">Password</Label>
<PasswordBox />
<Button HorizontalAlignment="Right" Width="100" Margin="0,10,0,5">Submit</Button>
</StackPanel>
</Window>
Die angefügte Eigenschaft wird einer TextBox
mithilfe der Syntax xmlNamespace:Class.Property
hinzugefügt.
Vollständiges Beispiel
Der folgende Code ist die vollständige TextBoxHelper
Klasse.
public static class TextBoxHelper
{
public static string GetPlaceholder(DependencyObject obj) =>
(string)obj.GetValue(PlaceholderProperty);
public static void SetPlaceholder(DependencyObject obj, string value) =>
obj.SetValue(PlaceholderProperty, value);
public static readonly DependencyProperty PlaceholderProperty =
DependencyProperty.RegisterAttached(
"Placeholder",
typeof(string),
typeof(TextBoxHelper),
new FrameworkPropertyMetadata(
defaultValue: null,
propertyChangedCallback: OnPlaceholderChanged)
);
private static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox textBoxControl)
{
if (!textBoxControl.IsLoaded)
{
// Ensure that the events are not added multiple times
textBoxControl.Loaded -= TextBoxControl_Loaded;
textBoxControl.Loaded += TextBoxControl_Loaded;
}
textBoxControl.TextChanged -= TextBoxControl_TextChanged;
textBoxControl.TextChanged += TextBoxControl_TextChanged;
// If the adorner exists, invalidate it to draw the current text
if (GetOrCreateAdorner(textBoxControl, out PlaceholderAdorner adorner))
adorner.InvalidateVisual();
}
}
private static void TextBoxControl_Loaded(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBoxControl)
{
textBoxControl.Loaded -= TextBoxControl_Loaded;
GetOrCreateAdorner(textBoxControl, out _);
}
}
private static void TextBoxControl_TextChanged(object sender, TextChangedEventArgs e)
{
if (sender is TextBox textBoxControl
&& GetOrCreateAdorner(textBoxControl, out PlaceholderAdorner adorner))
{
// Control has text. Hide the adorner.
if (textBoxControl.Text.Length > 0)
adorner.Visibility = Visibility.Hidden;
// Control has no text. Show the adorner.
else
adorner.Visibility = Visibility.Visible;
}
}
private static bool GetOrCreateAdorner(TextBox textBoxControl, out PlaceholderAdorner adorner)
{
// Get the adorner layer
AdornerLayer layer = AdornerLayer.GetAdornerLayer(textBoxControl);
// If null, it doesn't exist or the control's template isn't loaded
if (layer == null)
{
adorner = null;
return false;
}
// Layer exists, try to find the adorner
adorner = layer.GetAdorners(textBoxControl)?.OfType<PlaceholderAdorner>().FirstOrDefault();
// Adorner never added to control, so add it
if (adorner == null)
{
adorner = new PlaceholderAdorner(textBoxControl);
layer.Add(adorner);
}
return true;
}
public class PlaceholderAdorner : Adorner
{
public PlaceholderAdorner(TextBox textBox) : base(textBox) { }
protected override void OnRender(DrawingContext drawingContext)
{
TextBox textBoxControl = (TextBox)AdornedElement;
string placeholderValue = TextBoxHelper.GetPlaceholder(textBoxControl);
if (string.IsNullOrEmpty(placeholderValue))
return;
// Create the formatted text object
FormattedText text = new FormattedText(
placeholderValue,
System.Globalization.CultureInfo.CurrentCulture,
textBoxControl.FlowDirection,
new Typeface(textBoxControl.FontFamily,
textBoxControl.FontStyle,
textBoxControl.FontWeight,
textBoxControl.FontStretch),
textBoxControl.FontSize,
SystemColors.InactiveCaptionBrush,
VisualTreeHelper.GetDpi(textBoxControl).PixelsPerDip);
text.MaxTextWidth = System.Math.Max(textBoxControl.ActualWidth - textBoxControl.Padding.Left - textBoxControl.Padding.Right, 10);
text.MaxTextHeight = System.Math.Max(textBoxControl.ActualHeight, 10);
// Render based on padding of the control, to try and match where the textbox places text
Point renderingOffset = new Point(textBoxControl.Padding.Left, textBoxControl.Padding.Top);
// Template contains the content part; adjust sizes to try and align the text
if (textBoxControl.Template.FindName("PART_ContentHost", textBoxControl) is FrameworkElement part)
{
Point partPosition = part.TransformToAncestor(textBoxControl).Transform(new Point(0, 0));
renderingOffset.X += partPosition.X;
renderingOffset.Y += partPosition.Y;
text.MaxTextWidth = System.Math.Max(part.ActualWidth - renderingOffset.X, 10);
text.MaxTextHeight = System.Math.Max(part.ActualHeight, 10);
}
// Draw the text
drawingContext.DrawText(text, renderingOffset);
}
}
}
Public Class TextBoxHelper
Public Shared Function GetPlaceholder(obj As DependencyObject) As String
Return obj.GetValue(PlaceholderProperty)
End Function
Public Shared Sub SetPlaceholder(obj As DependencyObject, value As String)
obj.SetValue(PlaceholderProperty, value)
End Sub
Public Shared ReadOnly PlaceholderProperty As DependencyProperty =
DependencyProperty.RegisterAttached(
"Placeholder",
GetType(String),
GetType(TextBoxHelper),
New FrameworkPropertyMetadata(
defaultValue:=Nothing,
propertyChangedCallback:=AddressOf OnPlaceholderChanged)
)
Private Shared Sub OnPlaceholderChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim textBoxControl = TryCast(d, TextBox)
If textBoxControl IsNot Nothing Then
If Not textBoxControl.IsLoaded Then
'Ensure that the events are not added multiple times
RemoveHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded
AddHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded
End If
RemoveHandler textBoxControl.TextChanged, AddressOf TextBoxControl_TextChanged
AddHandler textBoxControl.TextChanged, AddressOf TextBoxControl_TextChanged
'If the adorner exists, invalidate it to draw the current text
Dim adorner As PlaceholderAdorner = Nothing
If GetOrCreateAdorner(textBoxControl, adorner) Then
adorner.InvalidateVisual()
End If
End If
End Sub
Private Shared Sub TextBoxControl_Loaded(sender As Object, e As RoutedEventArgs)
Dim textBoxControl As TextBox = TryCast(sender, TextBox)
If textBoxControl IsNot Nothing Then
RemoveHandler textBoxControl.Loaded, AddressOf TextBoxControl_Loaded
GetOrCreateAdorner(textBoxControl, Nothing)
End If
End Sub
Private Shared Sub TextBoxControl_TextChanged(sender As Object, e As TextChangedEventArgs)
Dim textBoxControl As TextBox = TryCast(sender, TextBox)
Dim adorner As PlaceholderAdorner = Nothing
If textBoxControl IsNot Nothing AndAlso GetOrCreateAdorner(textBoxControl, adorner) Then
If textBoxControl.Text.Length > 0 Then
'Control has text. Hide the adorner.
adorner.Visibility = Visibility.Hidden
Else
'Control has no text. Show the adorner.
adorner.Visibility = Visibility.Visible
End If
End If
End Sub
Private Shared Function GetOrCreateAdorner(textBoxControl As TextBox, ByRef adorner As PlaceholderAdorner) As Boolean
'Get the adorner layer
Dim layer As AdornerLayer = AdornerLayer.GetAdornerLayer(textBoxControl)
'If nothing, it doesn't exist or the control's template isn't loaded
If layer Is Nothing Then
adorner = Nothing
Return False
End If
'Layer exists, try to find the adorner
adorner = layer.GetAdorners(textBoxControl)?.OfType(Of PlaceholderAdorner)().FirstOrDefault()
'Adorner never added to control, so add it
If adorner Is Nothing Then
adorner = New PlaceholderAdorner(textBoxControl)
layer.Add(adorner)
End If
Return True
End Function
Public Class PlaceholderAdorner
Inherits Adorner
Public Sub New(adornedElement As UIElement)
MyBase.New(adornedElement)
End Sub
Protected Overrides Sub OnRender(drawingContext As DrawingContext)
Dim textBoxControl As TextBox = DirectCast(AdornedElement, TextBox)
Dim placeholderValue As String = TextBoxHelper.GetPlaceholder(textBoxControl)
If String.IsNullOrEmpty(placeholderValue) Then
Return
End If
'Create the formatted text object
Dim text As New FormattedText(
placeholderValue,
System.Globalization.CultureInfo.CurrentCulture,
textBoxControl.FlowDirection,
New Typeface(textBoxControl.FontFamily,
textBoxControl.FontStyle,
textBoxControl.FontWeight,
textBoxControl.FontStretch),
textBoxControl.FontSize,
SystemColors.InactiveCaptionBrush,
VisualTreeHelper.GetDpi(textBoxControl).PixelsPerDip)
text.MaxTextWidth = Math.Max(textBoxControl.ActualWidth - textBoxControl.Padding.Left - textBoxControl.Padding.Right, 10)
text.MaxTextHeight = Math.Max(textBoxControl.ActualHeight, 10)
'Render based on padding of the control, to try and match where the textbox places text
Dim renderingOffset As New Point(textBoxControl.Padding.Left, textBoxControl.Padding.Top)
'Template contains the content part; adjust sizes to try and align the text
Dim part As FrameworkElement = TryCast(textBoxControl.Template.FindName("PART_ContentHost", textBoxControl), FrameworkElement)
If part IsNot Nothing Then
Dim partPosition As Point = part.TransformToAncestor(textBoxControl).Transform(New Point(0, 0))
renderingOffset.X += partPosition.X
renderingOffset.Y += partPosition.Y
text.MaxTextWidth = Math.Max(part.ActualWidth - renderingOffset.X, 10)
text.MaxTextHeight = Math.Max(part.ActualHeight, 10)
End If
' Draw the text
drawingContext.DrawText(text, renderingOffset)
End Sub
End Class
End Class
Siehe auch
.NET Desktop feedback