Dies ist ein Beispiel, das zeigt, wie ein Wasserzeichen-Textfeld in WPF erstellt wird:
<Window x:Class="WaterMarkTextBoxDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WaterMarkTextBoxDemo"Height="200"Width="400"><Window.Resources><SolidColorBrush x:Key="brushWatermarkBackground"Color="White"/><SolidColorBrush x:Key="brushWatermarkForeground"Color="LightSteelBlue"/><SolidColorBrush x:Key="brushWatermarkBorder"Color="Indigo"/><BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/><local:TextInputToVisibilityConverter x:Key="TextInputToVisibilityConverter"/><Style x:Key="EntryFieldStyle"TargetType="Grid"><SetterProperty="HorizontalAlignment"Value="Stretch"/><SetterProperty="VerticalAlignment"Value="Center"/><SetterProperty="Margin"Value="20,0"/></Style></Window.Resources><GridBackground="LightBlue"><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><GridGrid.Row="0"Background="{StaticResource brushWatermarkBackground}"Style="{StaticResource EntryFieldStyle}"><TextBlockMargin="5,2"Text="This prompt dissappears as you type..."Foreground="{StaticResource brushWatermarkForeground}"Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}"/><TextBoxName="txtUserEntry"Background="Transparent"BorderBrush="{StaticResource brushWatermarkBorder}"/></Grid><GridGrid.Row="1"Background="{StaticResource brushWatermarkBackground}"Style="{StaticResource EntryFieldStyle}"><TextBlockMargin="5,2"Text="This dissappears as the control gets focus..."Foreground="{StaticResource brushWatermarkForeground}"><TextBlock.Visibility><MultiBindingConverter="{StaticResource TextInputToVisibilityConverter}"><BindingElementName="txtUserEntry2"Path="Text.IsEmpty"/><BindingElementName="txtUserEntry2"Path="IsFocused"/></MultiBinding></TextBlock.Visibility></TextBlock><TextBoxName="txtUserEntry2"Background="Transparent"BorderBrush="{StaticResource brushWatermarkBorder}"/></Grid></Grid></Window>
TextInputToVisibilityConverter ist definiert als:
using System;
using System.Windows.Data;
using System.Windows;
namespace WaterMarkTextBoxDemo{publicclassTextInputToVisibilityConverter:IMultiValueConverter{publicobjectConvert(object[] values,Type targetType,object parameter,System.Globalization.CultureInfo culture ){// Always test MultiValueConverter inputs for non-null// (to avoid crash bugs for views in the designer)if(values[0]isbool&& values[1]isbool){bool hasText =!(bool)values[0];bool hasFocus =(bool)values[1];if(hasFocus || hasText)returnVisibility.Collapsed;}returnVisibility.Visible;}publicobject[]ConvertBack(objectvalue,Type[] targetTypes,object parameter,System.Globalization.CultureInfo culture ){thrownewNotImplementedException();}}}
Hinweis: Dies ist nicht mein Code. Ich habe es hier gefunden , aber ich denke, das ist der beste Ansatz.
Der beste Ansatz? sicherlich nicht! Möchten Sie wirklich jedes Mal so viele Codezeilen eingeben, wenn Sie ein Wasserzeichen benötigen? Die Lösung mit einer angehängten Eigenschaft ist viel einfacher wiederzuverwenden ...
Thomas Levesque
5
Erwägen Sie, ein UserControl zu erstellen.
CSharper
6
Obwohl ich Ihre Bemühungen, der Community zu helfen, sehr schätze, muss ich wirklich sagen, dass dies alles andere als ein anständiger Ansatz ist.
R41n
2
Dieser Code wurde von Andy L. erstellt. Sie finden ihn im Codeprojekt .
Aloisdg Umzug auf codidact.com
440
Sie können ein Wasserzeichen erstellen, das TextBoxmit einer angehängten Eigenschaft zu jedem hinzugefügt werden kann . Hier ist die Quelle für die angehängte Eigenschaft:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;/// <summary>/// Class that provides the Watermark attached property/// </summary>publicstaticclassWatermarkService{/// <summary>/// Watermark Attached Dependency Property/// </summary>publicstaticreadonlyDependencyPropertyWatermarkProperty=DependencyProperty.RegisterAttached("Watermark",typeof(object),typeof(WatermarkService),newFrameworkPropertyMetadata((object)null,newPropertyChangedCallback(OnWatermarkChanged)));#region Private Fields/// <summary>/// Dictionary of ItemsControls/// </summary>privatestaticreadonlyDictionary<object,ItemsControl> itemsControls =newDictionary<object,ItemsControl>();#endregion/// <summary>/// Gets the Watermark property. This dependency property indicates the watermark for the control./// </summary>/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>/// <returns>The value of the Watermark property</returns>publicstaticobjectGetWatermark(DependencyObject d){return(object)d.GetValue(WatermarkProperty);}/// <summary>/// Sets the Watermark property. This dependency property indicates the watermark for the control./// </summary>/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>/// <param name="value">value of the property</param>publicstaticvoidSetWatermark(DependencyObject d,objectvalue){
d.SetValue(WatermarkProperty,value);}/// <summary>/// Handles changes to the Watermark property./// </summary>/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>privatestaticvoidOnWatermarkChanged(DependencyObject d,DependencyPropertyChangedEventArgs e){Control control =(Control)d;
control.Loaded+=Control_Loaded;if(d isComboBox){
control.GotKeyboardFocus+=Control_GotKeyboardFocus;
control.LostKeyboardFocus+=Control_Loaded;}elseif(d isTextBox){
control.GotKeyboardFocus+=Control_GotKeyboardFocus;
control.LostKeyboardFocus+=Control_Loaded;((TextBox)control).TextChanged+=Control_GotKeyboardFocus;}if(d isItemsControl&&!(d isComboBox)){ItemsControl i =(ItemsControl)d;// for Items property
i.ItemContainerGenerator.ItemsChanged+=ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);// for ItemsSource property DependencyPropertyDescriptor prop =DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i,ItemsSourceChanged);}}#region Event Handlers/// <summary>/// Handle the GotFocus event on the control/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>privatestaticvoidControl_GotKeyboardFocus(object sender,RoutedEventArgs e){Control c =(Control)sender;if(ShouldShowWatermark(c)){ShowWatermark(c);}else{RemoveWatermark(c);}}/// <summary>/// Handle the Loaded and LostFocus event on the control/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>privatestaticvoidControl_Loaded(object sender,RoutedEventArgs e){Control control =(Control)sender;if(ShouldShowWatermark(control)){ShowWatermark(control);}}/// <summary>/// Event handler for the items source changed event/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>privatestaticvoidItemsSourceChanged(object sender,EventArgs e){ItemsControl c =(ItemsControl)sender;if(c.ItemsSource!=null){if(ShouldShowWatermark(c)){ShowWatermark(c);}else{RemoveWatermark(c);}}else{ShowWatermark(c);}}/// <summary>/// Event handler for the items changed event/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>privatestaticvoidItemsChanged(object sender,ItemsChangedEventArgs e){ItemsControl control;if(itemsControls.TryGetValue(sender,out control)){if(ShouldShowWatermark(control)){ShowWatermark(control);}else{RemoveWatermark(control);}}}#endregion#region Helper Methods/// <summary>/// Remove the watermark from the specified element/// </summary>/// <param name="control">Element to remove the watermark from</param>privatestaticvoidRemoveWatermark(UIElement control){AdornerLayer layer =AdornerLayer.GetAdornerLayer(control);// layer could be null if control is no longer in the visual treeif(layer !=null){Adorner[] adorners = layer.GetAdorners(control);if(adorners ==null){return;}foreach(Adorner adorner in adorners){if(adorner isWatermarkAdorner){
adorner.Visibility=Visibility.Hidden;
layer.Remove(adorner);}}}}/// <summary>/// Show the watermark on the specified control/// </summary>/// <param name="control">Control to show the watermark on</param>privatestaticvoidShowWatermark(Control control){AdornerLayer layer =AdornerLayer.GetAdornerLayer(control);// layer could be null if control is no longer in the visual treeif(layer !=null){
layer.Add(newWatermarkAdorner(control,GetWatermark(control)));}}/// <summary>/// Indicates whether or not the watermark should be shown on the specified control/// </summary>/// <param name="c"><see cref="Control"/> to test</param>/// <returns>true if the watermark should be shown; false otherwise</returns>privatestaticboolShouldShowWatermark(Control c){if(c isComboBox){return(c asComboBox).Text==string.Empty;}elseif(c isTextBoxBase){return(c asTextBox).Text==string.Empty;}elseif(c isItemsControl){return(c asItemsControl).Items.Count==0;}else{returnfalse;}}#endregion}
Die angehängte Eigenschaft verwendet eine Klasse namens WatermarkAdorner, hier ist diese Quelle:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;/// <summary>/// Adorner for the watermark/// </summary>internalclassWatermarkAdorner:Adorner{#region Private Fields/// <summary>/// <see cref="ContentPresenter"/> that holds the watermark/// </summary>privatereadonlyContentPresenter contentPresenter;#endregion#region Constructor/// <summary>/// Initializes a new instance of the <see cref="WatermarkAdorner"/> class/// </summary>/// <param name="adornedElement"><see cref="UIElement"/> to be adorned</param>/// <param name="watermark">The watermark</param>publicWatermarkAdorner(UIElement adornedElement,object watermark):base(adornedElement){this.IsHitTestVisible=false;this.contentPresenter =newContentPresenter();this.contentPresenter.Content= watermark;this.contentPresenter.Opacity=0.5;this.contentPresenter.Margin=newThickness(Control.Margin.Left+Control.Padding.Left,Control.Margin.Top+Control.Padding.Top,0,0);if(this.ControlisItemsControl&&!(this.ControlisComboBox)){this.contentPresenter.VerticalAlignment=VerticalAlignment.Center;this.contentPresenter.HorizontalAlignment=HorizontalAlignment.Center;}// Hide the control adorner when the adorned element is hiddenBinding binding =newBinding("IsVisible");
binding.Source= adornedElement;
binding.Converter=newBooleanToVisibilityConverter();this.SetBinding(VisibilityProperty, binding);}#endregion#region Protected Properties/// <summary>/// Gets the number of children for the <see cref="ContainerVisual"/>./// </summary>protectedoverrideintVisualChildrenCount{get{return1;}}#endregion#region Private Properties/// <summary>/// Gets the control that is being adorned/// </summary>privateControlControl{get{return(Control)this.AdornedElement;}}#endregion#region Protected Overrides/// <summary>/// Returns a specified child <see cref="Visual"/> for the parent <see cref="ContainerVisual"/>./// </summary>/// <param name="index">A 32-bit signed integer that represents the index value of the child <see cref="Visual"/>. The value of index must be between 0 and <see cref="VisualChildrenCount"/> - 1.</param>/// <returns>The child <see cref="Visual"/>.</returns>protectedoverrideVisualGetVisualChild(int index){returnthis.contentPresenter;}/// <summary>/// Implements any custom measuring behavior for the adorner./// </summary>/// <param name="constraint">A size to constrain the adorner to.</param>/// <returns>A <see cref="Size"/> object representing the amount of layout space needed by the adorner.</returns>protectedoverrideSizeMeasureOverride(Size constraint){// Here's the secret to getting the adorner to cover the whole controlthis.contentPresenter.Measure(Control.RenderSize);returnControl.RenderSize;}/// <summary>/// When overridden in a derived class, positions child elements and determines a size for a <see cref="FrameworkElement"/> derived class. /// </summary>/// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param>/// <returns>The actual size used.</returns>protectedoverrideSizeArrangeOverride(Size finalSize){this.contentPresenter.Arrange(newRect(finalSize));return finalSize;}#endregion}
Jetzt können Sie jeder TextBox wie folgt ein Wasserzeichen hinzufügen:
<AdornerDecorator><TextBox x:Name="SearchTextBox"><controls:WatermarkService.Watermark><TextBlock>Type here to search text</TextBlock></controls:WatermarkService.Watermark></TextBox></AdornerDecorator>
Das Wasserzeichen kann alles sein, was Sie wollen (Text, Bilder ...). Dieses Wasserzeichen funktioniert nicht nur für TextBoxen, sondern auch für ComboBoxen und ItemControls.
Ich habe es gelöst, indem ich die Margin-Zuweisung des WatermarkAdorner-Konstruktors wie folgt geändert habe: Margin = new Thickness (Control.Padding.Left, Control.Padding.Top + 1, Control.Padding.Right, Control.Padding.Bottom)
JoanComasFdz
3
@JohnMyczek Um das Wasserzeichen zu lokalisieren: Wie kann ich die TextBox.Text in der Wateram xaml-Deklaration an eine Eigenschaft aus ViewModel binden?
JoanComasFdz
7
@Matze @JoanComasFdz So kann ich die TextBlock.TextEigenschaft an mein Ansichtsmodell binden (in den WatermarkAdornerKonstruktor einfügen ): FrameworkElement feWatermark = watermark as FrameworkElement;if(feWatermark != null && feWatermark.DataContext == null) { feWatermark.DataContext = this.Control.DataContext; }
Sean Hall
9
Mögliche Speicherverbindung hier. Sie fügen dem internen statischen Wörterbuch Steuerelemente mit Wasserzeichen hinzu, entfernen sie jedoch nie. Dies wird wahrscheinlich verhindern, dass Ihre Ansichten Müll gesammelt werden, sobald Sie damit fertig sind. Ich würde hier eine schwache Referenz in Betracht ziehen.
Jared G
3
Neben dem statischen Wörterbuch der Elementsteuerungen verliert der PropertyDescriptor-Code auch Speicher. Sie müssen RemoveValueChanged () aufrufen. Seien Sie also vorsichtig, wenn Sie diesen Code verwenden.
Muku
284
Nur mit XAML, keine Erweiterungen, keine Konverter:
<Grid><TextBoxWidth="250"VerticalAlignment="Center"HorizontalAlignment="Left" x:Name="SearchTermTextBox"Margin="5"/><TextBlockIsHitTestVisible="False"Text="Enter Search Term Here"VerticalAlignment="Center"HorizontalAlignment="Left"Margin="10,0,0,0"Foreground="DarkGray"><TextBlock.Style><StyleTargetType="{x:Type TextBlock}"><SetterProperty="Visibility"Value="Collapsed"/><Style.Triggers><DataTriggerBinding="{Binding Text, ElementName=SearchTermTextBox}"Value=""><SetterProperty="Visibility"Value="Visible"/></DataTrigger></Style.Triggers></Style></TextBlock.Style></TextBlock></Grid>
Extrem einfach, am besten auch. Ich weiß nicht, warum Sie all diese anderen verwenden würden, wenn Sie diese 10 Zeilen XAML-Skript haben könnten, und das war's. Vielen Dank.
dj.lnxss
4
Sie können eine hinzufügen möchten , Padding="6,3,0,0"um die TextBlock.
Aloisdg Umzug auf codidact.com
1
Sehr schön, aber es funktioniert nicht unter Windows Phone Silverlight :-(
Andrea Antonangeli
14
Wie würde man dies zu einer wiederverwendbaren Kontrollvorlage machen?
Richard
2
@cyrianox Dies liegt daran, dass die Password-Eigenschaft einer PasswordBox aus Sicherheitsgründen nicht bindbar ist. Sie können es anhand dieses Beispiels hier bindbar machen: wpftutorial.net/PasswordBox.html Es ist jedoch wahrscheinlich schneller und einfacher, nur das PasswordChanged-Ereignis und den Code dahinter zu verwenden, um die Sichtbarkeit in diesem Fall festzulegen .
apc
54
Ich kann nicht glauben, dass niemand das offensichtliche Extended WPF Toolkit - WatermarkTextBox von Xceed gepostet hat. Es funktioniert ganz gut und ist Open Source für den Fall, dass Sie anpassen möchten.
Auf meinem Win8-Computer haben alle WPF Toolkit-Steuerelemente Windows 7-Stile (abgerundete Ecken usw.). Und jedes WPF-Toolkit-Steuerelement sieht beim Mischen mit Standardsteuerelementen völlig fehl am Platz aus.
Gman
1
Der Ansatz "Attached Property" von John Myczek weist einen Fehler auf, bei dem das Wasserzeichen durchblutet und weiterhin sichtbar ist, wenn das Textfeld von einem anderen Element abgedeckt wird. Diese Lösung hat dieses Problem nicht. (Ich wünschte, ich hätte das früher bemerkt, da ich das Toolkit sowieso schon benutze). Verdient mehr positive Stimmen.
Dax Fohl
Die Lösung von John Myczek weist auch einen offensichtlichen Speicherverlust auf, bei dem der WatermarkService in einem statischen Wörterbuch einen Verweis auf jedes ItemsControl speichert, an das ein Wasserzeichen angehängt wird. Es könnte definitiv behoben werden, aber ich werde die Extended WPF Toolkit-Version ausprobieren.
Ok, es sind vielleicht nicht 3 Zeilen XAML-formatiert, aber es ist so ziemlich einfach.
Zu beachten ist jedoch, dass für die Text-Eigenschaft eine nicht standardmäßige Erweiterungsmethode namens "IsEmpty" verwendet wird. Sie müssen dies selbst implementieren, der Artikel scheint dies jedoch nicht zu erwähnen.
Die TextBox sollte haben IsHitTestVisible="False". Außerdem sollte es nach der TextBox kommen, da es sonst möglicherweise nicht sichtbar ist, wenn die TextBox Hintergrund hat.
Aneves
Dieser Artikel in CodeProject ist einfach schlecht.
Ich habe die Lösung von John Myczek und ihre Kommentare zur Kompatibilität mit ComboBoxund gesehen PasswordBox, also habe ich die Lösung von John Myczek verbessert, und hier ist sie:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;/// <summary>/// Class that provides the Watermark attached property/// </summary>publicstaticclassWatermarkService{/// <summary>/// Watermark Attached Dependency Property/// </summary>publicstaticreadonlyDependencyPropertyWatermarkProperty=DependencyProperty.RegisterAttached("Watermark",typeof(object),typeof(WatermarkService),newFrameworkPropertyMetadata((object)null,newPropertyChangedCallback(OnWatermarkChanged)));#region Private Fields/// <summary>/// Dictionary of ItemsControls/// </summary>privatestaticreadonlyDictionary<object,ItemsControl> itemsControls =newDictionary<object,ItemsControl>();#endregion/// <summary>/// Gets the Watermark property. This dependency property indicates the watermark for the control./// </summary>/// <param name="d"><see cref="DependencyObject"/> to get the property from</param>/// <returns>The value of the Watermark property</returns>publicstaticobjectGetWatermark(DependencyObject d){return(object)d.GetValue(WatermarkProperty);}/// <summary>/// Sets the Watermark property. This dependency property indicates the watermark for the control./// </summary>/// <param name="d"><see cref="DependencyObject"/> to set the property on</param>/// <param name="value">value of the property</param>publicstaticvoidSetWatermark(DependencyObject d,objectvalue){
d.SetValue(WatermarkProperty,value);}/// <summary>/// Handles changes to the Watermark property./// </summary>/// <param name="d"><see cref="DependencyObject"/> that fired the event</param>/// <param name="e">A <see cref="DependencyPropertyChangedEventArgs"/> that contains the event data.</param>privatestaticvoidOnWatermarkChanged(DependencyObject d,DependencyPropertyChangedEventArgs e){Control control =(Control)d;
control.Loaded+=Control_Loaded;if(d isTextBox|| d isPasswordBox){
control.GotKeyboardFocus+=Control_GotKeyboardFocus;
control.LostKeyboardFocus+=Control_Loaded;}elseif(d isComboBox){
control.GotKeyboardFocus+=Control_GotKeyboardFocus;
control.LostKeyboardFocus+=Control_Loaded;(d asComboBox).SelectionChanged+=newSelectionChangedEventHandler(SelectionChanged);}elseif(d isItemsControl){ItemsControl i =(ItemsControl)d;// for Items property
i.ItemContainerGenerator.ItemsChanged+=ItemsChanged;
itemsControls.Add(i.ItemContainerGenerator, i);// for ItemsSource property DependencyPropertyDescriptor prop =DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
prop.AddValueChanged(i,ItemsSourceChanged);}}/// <summary>/// Event handler for the selection changed event/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>privatestaticvoidSelectionChanged(object sender,SelectionChangedEventArgs e){Control control =(Control)sender;if(ShouldShowWatermark(control)){ShowWatermark(control);}else{RemoveWatermark(control);}}#region Event Handlers/// <summary>/// Handle the GotFocus event on the control/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>privatestaticvoidControl_GotKeyboardFocus(object sender,RoutedEventArgs e){Control c =(Control)sender;if(ShouldShowWatermark(c)){RemoveWatermark(c);}}/// <summary>/// Handle the Loaded and LostFocus event on the control/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="RoutedEventArgs"/> that contains the event data.</param>privatestaticvoidControl_Loaded(object sender,RoutedEventArgs e){Control control =(Control)sender;if(ShouldShowWatermark(control)){ShowWatermark(control);}}/// <summary>/// Event handler for the items source changed event/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="EventArgs"/> that contains the event data.</param>privatestaticvoidItemsSourceChanged(object sender,EventArgs e){ItemsControl c =(ItemsControl)sender;if(c.ItemsSource!=null){if(ShouldShowWatermark(c)){ShowWatermark(c);}else{RemoveWatermark(c);}}else{ShowWatermark(c);}}/// <summary>/// Event handler for the items changed event/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="e">A <see cref="ItemsChangedEventArgs"/> that contains the event data.</param>privatestaticvoidItemsChanged(object sender,ItemsChangedEventArgs e){ItemsControl control;if(itemsControls.TryGetValue(sender,out control)){if(ShouldShowWatermark(control)){ShowWatermark(control);}else{RemoveWatermark(control);}}}#endregion#region Helper Methods/// <summary>/// Remove the watermark from the specified element/// </summary>/// <param name="control">Element to remove the watermark from</param>privatestaticvoidRemoveWatermark(UIElement control){AdornerLayer layer =AdornerLayer.GetAdornerLayer(control);// layer could be null if control is no longer in the visual treeif(layer !=null){Adorner[] adorners = layer.GetAdorners(control);if(adorners ==null){return;}foreach(Adorner adorner in adorners){if(adorner isWatermarkAdorner){
adorner.Visibility=Visibility.Hidden;
layer.Remove(adorner);}}}}/// <summary>/// Show the watermark on the specified control/// </summary>/// <param name="control">Control to show the watermark on</param>privatestaticvoidShowWatermark(Control control){AdornerLayer layer =AdornerLayer.GetAdornerLayer(control);// layer could be null if control is no longer in the visual treeif(layer !=null){
layer.Add(newWatermarkAdorner(control,GetWatermark(control)));}}/// <summary>/// Indicates whether or not the watermark should be shown on the specified control/// </summary>/// <param name="c"><see cref="Control"/> to test</param>/// <returns>true if the watermark should be shown; false otherwise</returns>privatestaticboolShouldShowWatermark(Control c){if(c isComboBox){return(c asComboBox).SelectedItem==null;//return (c as ComboBox).Text == string.Empty;}elseif(c isTextBoxBase){return(c asTextBox).Text==string.Empty;}elseif(c isPasswordBox){return(c asPasswordBox).Password==string.Empty;}elseif(c isItemsControl){return(c asItemsControl).Items.Count==0;}else{returnfalse;}}#endregion}
Jetzt ComboBoxkann a auch sein Editableund PasswordBoxkann auch ein Wasserzeichen hinzufügen. Vergessen Sie nicht, den obigen Kommentar von JoanComasFdz zu verwenden, um das Randproblem zu lösen.
Und natürlich geht der ganze Kredit an John Myczek.
Das ist in der Tat eine verbesserte Version des schönen Stücks @ John-Myczek-Code und es funktionierte Geldstrafe für Kombinationsfelder. Danke euch beiden!
Tolle Lösung. Warum die Foreground-Eigenschaft beschatten? SetBinding (TextProperty, new Binding ()) löst InvalidOperationException aus: Für die bidirektionale Bindung ist Path oder XPath erforderlich.
Tim Murphy
Ich verstecke die Foreground-Eigenschaft, weil TextBoxWatermarked sie für eigene Zwecke verwendet. Ich weiß nicht, warum InvalidOperationException ausgelöst wird. Wenn Sie WPF verwenden (ich habe es mit Silverlight verwendet), müssen Sie möglicherweise null anstelle von new Binding () übergeben.
Vitaliy Ulantikov
2
Um diesen Code in WPF zu verwenden, verwenden Sie BindingOperations.ClearBinding(this, TextProperty)statt SetBinding(TextProperty, new Binding())an beiden Stellen.
Sebastian Krysmanski
1
Dies ändert sich tatsächlich Textzum Wasserzeichen. Würde nicht für mich arbeiten.
Hummerismus
Wahrscheinlich nützlich, um Namespace-Zeilen hinzuzufügen oder einige dieser Dinge vollständig zu qualifizieren.
Richard
6
Bei der Verwendung des Codes von @ john-myczek mit einer gebundenen TextBox stieß ich auf einige Schwierigkeiten . Da die TextBox beim Aktualisieren kein Fokusereignis auslöst, bleibt das Wasserzeichen unter dem neuen Text sichtbar. Um dies zu beheben, habe ich einfach einen weiteren Ereignishandler hinzugefügt:
Ich wünschte, ich hätte diese Antwort bemerkt, bevor ich sie selbst gemacht hätte.
Hummerismus
5
@Veton - Ich mag die Einfachheit Ihrer Lösung sehr, aber mein Ruf ist noch nicht hoch genug, um Sie zu stoßen.
@ Tim Murphy - Dieser Fehler "Zwei-Wege-Bindung erfordert Pfad oder XPath" war eine einfache Lösung ... aktualisierter Code, einschließlich einiger anderer kleiner Verbesserungen (nur WPF-getestet):
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;publicclassTextBoxWatermarked:TextBox{publicstringWatermark{get{return(string)GetValue(WaterMarkProperty);}set{SetValue(WaterMarkProperty,value);}}publicstaticreadonlyDependencyPropertyWaterMarkProperty=DependencyProperty.Register("Watermark",typeof(string),typeof(TextBoxWatermarked),newPropertyMetadata(newPropertyChangedCallback(OnWatermarkChanged)));privatebool _isWatermarked =false;privateBinding _textBinding =null;publicTextBoxWatermarked(){Loaded+=(s, ea)=>ShowWatermark();}protectedoverridevoidOnGotFocus(RoutedEventArgs e){base.OnGotFocus(e);HideWatermark();}protectedoverridevoidOnLostFocus(RoutedEventArgs e){base.OnLostFocus(e);ShowWatermark();}privatestaticvoidOnWatermarkChanged(DependencyObject sender,DependencyPropertyChangedEventArgs ea){var tbw = sender asTextBoxWatermarked;if(tbw ==null||!tbw.IsLoaded)return;//needed to check IsLoaded so that we didn't dive into the ShowWatermark() routine before initial Bindings had been made
tbw.ShowWatermark();}privatevoidShowWatermark(){if(String.IsNullOrEmpty(Text)&&!String.IsNullOrEmpty(Watermark)){
_isWatermarked =true;//save the existing binding so it can be restored
_textBinding =BindingOperations.GetBinding(this,TextProperty);//blank out the existing binding so we can throw in our WatermarkBindingOperations.ClearBinding(this,TextProperty);//set the signature watermark grayForeground=newSolidColorBrush(Colors.Gray);//display our watermark textText=Watermark;}}privatevoidHideWatermark(){if(_isWatermarked){
_isWatermarked =false;ClearValue(ForegroundProperty);Text="";if(_textBinding !=null)SetBinding(TextProperty, _textBinding);}}}
Dies kann helfen, dies mit Ihrem Code zu überprüfen. Wenn es auf das Kennwortfeld angewendet wird, wird das Kennwort angezeigt, das bei Verwendungstypen verschwindet.
Der Konverter, wie er jetzt geschrieben ist, ist nicht erforderlich, dass es sich um einen MultiConverter handelt, aber in dieser Version kann er leicht erweitert werden
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPFControls{classShadowConverter:IMultiValueConverter{#region Implementation of IMultiValueConverterpublicobjectConvert(object[] values,Type targetType,object parameter,CultureInfo culture){var text =(string) values[0];return text ==string.Empty?Visibility.Visible:Visibility.Collapsed;}publicobject[]ConvertBack(objectvalue,Type[] targetTypes,object parameter,CultureInfo culture){returnnewobject[0];}#endregion}}
und schließlich den Code dahinter:
using System.Windows;
using System.Windows.Controls;
namespace WPFControls{/// <summary>/// Interaction logic for ShadowedTextBox.xaml/// </summary>publicpartialclassShadowedTextBox:UserControl{publiceventTextChangedEventHandlerTextChanged;publicShadowedTextBox(){InitializeComponent();}publicstaticreadonlyDependencyPropertyWatermarkProperty=DependencyProperty.Register("Watermark",typeof(string),typeof(ShadowedTextBox),newUIPropertyMetadata(string.Empty));publicstaticreadonlyDependencyPropertyTextProperty=DependencyProperty.Register("Text",typeof(string),typeof(ShadowedTextBox),newUIPropertyMetadata(string.Empty));publicstaticreadonlyDependencyPropertyTextChangedProperty=DependencyProperty.Register("TextChanged",typeof(TextChangedEventHandler),typeof(ShadowedTextBox),newUIPropertyMetadata(null));publicstringWatermark{get{return(string)GetValue(WatermarkProperty);}set{SetValue(WatermarkProperty,value);}}publicstringText{get{return(string)GetValue(TextProperty);}set{SetValue(TextProperty,value);}}privatevoid textBox_TextChanged(object sender,TextChangedEventArgs e){if(TextChanged!=null)TextChanged(this, e);}publicvoidClear(){
textBox.Clear();}}}
MahApps.Metro für WPF verfügt über eine integrierte Wasserzeichensteuerung, wenn Sie lieber nicht selbst rollen möchten . Es ist ziemlich einfach zu bedienen.
<AdornerDecorator><TextBoxName="txtSomeText"Width="200"HorizontalAlignment="Right"><Controls:TextBoxHelper.Watermark>I'm a watermark!</Controls:TextBoxHelper.Watermark></TextBox></AdornerDecorator>
Dies ist ein Textfeld mit transparentem Hintergrund, der ein Etikett überlagert. Der graue Text des Etiketts wird durch einen Datenauslöser transparent, der immer dann ausgelöst wird, wenn der gebundene Text eine andere als eine leere Zeichenfolge ist.
Um die Wiederverwendbarkeit dieses Stils zu verbessern, können Sie auch eine Reihe angehängter Eigenschaften erstellen, um den tatsächlichen Text, die Farbe, die Ausrichtung usw. des Cue-Banners zu steuern.
Dies ist ein perfektes Beispiel, das beschreibt, wie man es nicht macht, insbesondere mit WPF.
Alexandru Dicu
0
Diese Technik verwendet die Background-Eigenschaft, um Platzhalter-Textfelder anzuzeigen / auszublenden. Platzhalter wird als Ereignis angezeigt, wenn Textbox den Fokus hat
Wie es funktioniert:
Wenn leer, wird der TextBox-Hintergrund auf Transparent gesetzt, um PlaceHolder-Text anzuzeigen.
Wenn der Hintergrund nicht leer ist, stellen Sie Weiß ein, um den PlaceHolder-Text zu verdecken.
Hier ist ein einfaches Beispiel. Für meine eigenen Zwecke habe ich daraus ein UserControl gemacht.
Sie können einen separaten Wert für den eingegebenen Text beibehalten und ihn zusammen mit dem Feld "Text" des Textfelds in den Ereignissen "GotFocus" und "LostFocus" festlegen. Wenn Sie den Fokus erhalten, möchten Sie das Textfeld löschen, wenn kein Wert vorhanden ist. Wenn Sie den Fokus verlieren, sollten Sie den Wert "Text" aus dem Textfeld abrufen und dann den Wert "Text" des Textfelds auf den Platzhalter zurücksetzen, wenn dieser leer ist.
Wenn nicht das Wasserzeichen die Sichtbarkeit auf den Fokuszustand der Kontrolle abhängig ist, möchten Sie es hängt davon ab , ob der Benutzer einen beliebigen Text eingegeben hat, können Sie John Myczek Antwort aktualisieren (von OnWatermarkChangedunten) zu
Dies ist sinnvoller, wenn Ihr Textfeld beim Anzeigen des Formulars oder bei der Datenbindung an die Text-Eigenschaft automatisch fokussiert wird.
Auch wenn Ihr Wasserzeichen ist immer nur eine Zeichenfolge, und Sie müssen den Stil des Wasserzeichens den Stil der Textbox passen, dann in dem Adorner tun:
Hier ist mein Ansatz Großartig für MVVM, wo ich auch überprüfe, ob das Textfeld den Fokus hat. Sie können auch einen regulären Auslöser nur für den Textwert verwenden. Der Punkt ist, dass ich nur das Hintergrundbild ändere, wenn sich der Wert ändert:
Ich beschloss, dies über ein Verhalten zu lösen. Es verwendet eine HintEigenschaft, um den anzuzeigenden Text zu definieren (kann auch ein Objekt sein, wenn Sie dies bevorzugen) und eine ValueEigenschaft, um zu bewerten, ob der Hinweis sichtbar sein soll oder nicht.
Das Verhalten wird wie folgt deklariert:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;
using System.Windows.Media;publicclassHintBehavior:Behavior<ContentControl>{publicstaticreadonlyDependencyPropertyHintProperty=DependencyProperty.Register("Hint",typeof(string),typeof(HintBehavior)//, new FrameworkPropertyMetadata(null, OnHintChanged));publicstringHint{get{return(string)GetValue(HintProperty);}set{SetValue(HintProperty,value);}}publicstaticreadonlyDependencyPropertyValueProperty=DependencyProperty.Register("Value",typeof(object),typeof(HintBehavior),newFrameworkPropertyMetadata(null,OnValueChanged));privatestaticvoidOnValueChanged(DependencyObject d,DependencyPropertyChangedEventArgs e){var visible = e.NewValue==null;
d.SetValue(VisibilityProperty, visible ?Visibility.Visible:Visibility.Collapsed);}publicobjectValue{get{returnGetValue(ValueProperty);}set{SetValue(ValueProperty,value);}}publicstaticreadonlyDependencyPropertyVisibilityProperty=DependencyProperty.Register("Visibility",typeof(Visibility),typeof(HintBehavior),newFrameworkPropertyMetadata(Visibility.Visible//, new PropertyChangedCallback(OnVisibilityChanged)));publicVisibilityVisibility{get{return(Visibility)GetValue(VisibilityProperty);}set{SetValue(VisibilityProperty,value);}}publicstaticreadonlyDependencyPropertyForegroundProperty=DependencyProperty.Register("Foreground",typeof(Brush),typeof(HintBehavior),newFrameworkPropertyMetadata(newSolidColorBrush(Colors.DarkGray)//, new PropertyChangedCallback(OnForegroundChanged)));publicBrushForeground{get{return(Brush)GetValue(ForegroundProperty);}set{SetValue(ForegroundProperty,value);}}publicstaticreadonlyDependencyPropertyMarginProperty=DependencyProperty.Register("Margin",typeof(Thickness),typeof(HintBehavior),newFrameworkPropertyMetadata(newThickness(4,5,0,0)//, new PropertyChangedCallback(OnMarginChanged)));publicThicknessMargin{get{return(Thickness)GetValue(MarginProperty);}set{SetValue(MarginProperty,value);}}privatestaticResourceDictionary _hintBehaviorResources;publicstaticResourceDictionaryHintBehaviorResources{get{if(_hintBehaviorResources ==null){var res =newResourceDictionary{Source=newUri("/Mayflower.Client.Core;component/Behaviors/HintBehaviorResources.xaml",UriKind.RelativeOrAbsolute)};
_hintBehaviorResources = res;}return _hintBehaviorResources;}}protectedoverridevoidOnAttached(){base.OnAttached();var t =(ControlTemplate)HintBehaviorResources["HintBehaviorWrapper"];AssociatedObject.Template= t;AssociatedObject.Loaded+=OnLoaded;}privatevoidOnLoaded(object sender,RoutedEventArgs e){AssociatedObject.Loaded-=OnLoaded;var label =(Label)AssociatedObject.Template.FindName("PART_HintLabel",AssociatedObject);
label.DataContext=this;//label.Content = "Hello...";
label.SetBinding(UIElement.VisibilityProperty,newBinding("Visibility"){Source=this,Mode=BindingMode.OneWay});
label.SetBinding(ContentControl.ContentProperty,newBinding("Hint"){Source=this,Mode=BindingMode.OneWay});
label.SetBinding(Control.ForegroundProperty,newBinding("Foreground"){Source=this,Mode=BindingMode.OneWay});
label.SetBinding(FrameworkElement.MarginProperty,newBinding("Margin"){Source=this,Mode=BindingMode.OneWay});}}
Es umschließt das Ziel mit einer eigenen Vorlage und fügt eine Beschriftung hinzu:
Um es zu verwenden, fügen Sie es einfach als Verhalten hinzu und binden Sie Ihre Werte (in meinem Fall füge ich es in eine ControlTemplate ein, daher die Bindung):
Ich würde mich über Feedback freuen, wenn dies als saubere Lösung angesehen wird. Es erfordert keine statischen Wörterbücher und hat daher keinen Speicherverlust.
Antworten:
Dies ist ein Beispiel, das zeigt, wie ein Wasserzeichen-Textfeld in WPF erstellt wird:
TextInputToVisibilityConverter ist definiert als:
Hinweis: Dies ist nicht mein Code. Ich habe es hier gefunden , aber ich denke, das ist der beste Ansatz.
quelle
Sie können ein Wasserzeichen erstellen, das
TextBox
mit einer angehängten Eigenschaft zu jedem hinzugefügt werden kann . Hier ist die Quelle für die angehängte Eigenschaft:Die angehängte Eigenschaft verwendet eine Klasse namens
WatermarkAdorner
, hier ist diese Quelle:Jetzt können Sie jeder TextBox wie folgt ein Wasserzeichen hinzufügen:
Das Wasserzeichen kann alles sein, was Sie wollen (Text, Bilder ...). Dieses Wasserzeichen funktioniert nicht nur für TextBoxen, sondern auch für ComboBoxen und ItemControls.
Dieser Code wurde aus diesem Blog-Beitrag angepasst .
quelle
TextBlock.Text
Eigenschaft an mein Ansichtsmodell binden (in denWatermarkAdorner
Konstruktor einfügen ):FrameworkElement feWatermark = watermark as FrameworkElement;
if(feWatermark != null && feWatermark.DataContext == null)
{feWatermark.DataContext = this.Control.DataContext;
}Nur mit XAML, keine Erweiterungen, keine Konverter:
quelle
Padding="6,3,0,0"
um dieTextBlock
.Ich kann nicht glauben, dass niemand das offensichtliche Extended WPF Toolkit - WatermarkTextBox von Xceed gepostet hat. Es funktioniert ganz gut und ist Open Source für den Fall, dass Sie anpassen möchten.
quelle
Es gibt einen Artikel über CodeProject, wie es in "3 Zeilen XAML" gemacht wird.
Ok, es sind vielleicht nicht 3 Zeilen XAML-formatiert, aber es ist so ziemlich einfach.
Zu beachten ist jedoch, dass für die Text-Eigenschaft eine nicht standardmäßige Erweiterungsmethode namens "IsEmpty" verwendet wird. Sie müssen dies selbst implementieren, der Artikel scheint dies jedoch nicht zu erwähnen.
quelle
IsHitTestVisible="False"
. Außerdem sollte es nach der TextBox kommen, da es sonst möglicherweise nicht sichtbar ist, wenn die TextBox Hintergrund hat.Text.IsEmpty
funktioniert es: IsEmpty wird aus CollectionView.IsEmpty aufgelöstIch habe die Lösung von John Myczek und ihre Kommentare zur Kompatibilität mit
ComboBox
und gesehenPasswordBox
, also habe ich die Lösung von John Myczek verbessert, und hier ist sie:Jetzt
ComboBox
kann a auch seinEditable
undPasswordBox
kann auch ein Wasserzeichen hinzufügen. Vergessen Sie nicht, den obigen Kommentar von JoanComasFdz zu verwenden, um das Randproblem zu lösen.Und natürlich geht der ganze Kredit an John Myczek.
quelle
Einfache Lösung mit Stil:
Tolle Lösung:
https://code.msdn.microsoft.com/windowsdesktop/In-place-hit-messages-for-18db3a6c
quelle
Diese Bibliothek hat ein Wasserzeichen.
Nuget-Paket
Beispielnutzung:
quelle
Ich habe eine reine Code-Implementierung erstellt, die auch für WPF und Silverlight gut funktioniert:
Verwendungszweck:
quelle
BindingOperations.ClearBinding(this, TextProperty)
stattSetBinding(TextProperty, new Binding())
an beiden Stellen.Text
zum Wasserzeichen. Würde nicht für mich arbeiten.Bei der Verwendung des Codes von @ john-myczek mit einer gebundenen TextBox stieß ich auf einige Schwierigkeiten . Da die TextBox beim Aktualisieren kein Fokusereignis auslöst, bleibt das Wasserzeichen unter dem neuen Text sichtbar. Um dies zu beheben, habe ich einfach einen weiteren Ereignishandler hinzugefügt:
quelle
@Veton - Ich mag die Einfachheit Ihrer Lösung sehr, aber mein Ruf ist noch nicht hoch genug, um Sie zu stoßen.
@ Tim Murphy - Dieser Fehler "Zwei-Wege-Bindung erfordert Pfad oder XPath" war eine einfache Lösung ... aktualisierter Code, einschließlich einiger anderer kleiner Verbesserungen (nur WPF-getestet):
quelle
Sie können
GetFocus()
undLostFocus()
Ereignisse verwenden, um dies zu tunHier ist das Beispiel:
quelle
einfachster Weg zum WaterMark Of TextBox
und fügen Sie das Textfeld StaticResource-Stil hinzu
quelle
Dies kann helfen, dies mit Ihrem Code zu überprüfen. Wenn es auf das Kennwortfeld angewendet wird, wird das Kennwort angezeigt, das bei Verwendungstypen verschwindet.
quelle
Nun, hier ist meins: nicht unbedingt das Beste, aber da es einfach ist, ist es einfach, es nach Ihrem Geschmack zu bearbeiten.
Der Konverter, wie er jetzt geschrieben ist, ist nicht erforderlich, dass es sich um einen MultiConverter handelt, aber in dieser Version kann er leicht erweitert werden
und schließlich den Code dahinter:
quelle
quelle
MahApps.Metro für WPF verfügt über eine integrierte Wasserzeichensteuerung, wenn Sie lieber nicht selbst rollen möchten . Es ist ziemlich einfach zu bedienen.
quelle
Richten Sie das Textfeld mit Platzhaltertext in einer weichen Farbe ein ...
Wenn das Textfeld den Fokus erhält, löschen Sie es und ändern Sie die Textfarbe
quelle
Hier ist die einfachste Lösung:
Dies ist ein Textfeld mit transparentem Hintergrund, der ein Etikett überlagert. Der graue Text des Etiketts wird durch einen Datenauslöser transparent, der immer dann ausgelöst wird, wenn der gebundene Text eine andere als eine leere Zeichenfolge ist.
quelle
Siehe auch diese Antwort . Sie können dies viel einfacher mit einem VisualBrush und einigen Triggern in einem Stil erreichen:
Um die Wiederverwendbarkeit dieses Stils zu verbessern, können Sie auch eine Reihe angehängter Eigenschaften erstellen, um den tatsächlichen Text, die Farbe, die Ausrichtung usw. des Cue-Banners zu steuern.
quelle
Hallo, ich habe diese Aufgabe in ein Verhalten umgesetzt. Sie müssen also nur so etwas zu Ihrem Textfeld hinzufügen
Meinen Blogbeitrag finden Sie hier
quelle
Meine Lösung ist ganz einfach.
In meinem Anmeldefenster. das xaml ist so.
Der Code ist so.
Entscheiden Sie sich einfach dafür, das Wasserzeichen-Textfeld auszublenden oder anzuzeigen. Obwohl nicht schön, aber gut funktionieren.
quelle
Diese Technik verwendet die Background-Eigenschaft, um Platzhalter-Textfelder anzuzeigen / auszublenden.
Platzhalter wird als Ereignis angezeigt, wenn Textbox den Fokus hat
Wie es funktioniert:
Hier ist ein einfaches Beispiel. Für meine eigenen Zwecke habe ich daraus ein UserControl gemacht.
Hier ist der ValueConverter zum Erkennen nicht leerer Zeichenfolgen im DataTrigger.
quelle
Sie können einen separaten Wert für den eingegebenen Text beibehalten und ihn zusammen mit dem Feld "Text" des Textfelds in den Ereignissen "GotFocus" und "LostFocus" festlegen. Wenn Sie den Fokus erhalten, möchten Sie das Textfeld löschen, wenn kein Wert vorhanden ist. Wenn Sie den Fokus verlieren, sollten Sie den Wert "Text" aus dem Textfeld abrufen und dann den Wert "Text" des Textfelds auf den Platzhalter zurücksetzen, wenn dieser leer ist.
Dann müssen Sie nur noch sicherstellen, dass der Wert "Text" des Textfelds mit dem Platzhaltertext initialisiert ist.
Sie können dies weiter in eine Klasse extrahieren, die die "TextBox" -Klasse erweitert, und sie dann in Ihrem gesamten Projekt wiederverwenden.
Und dann kann dies direkt in der xaml hinzugefügt werden.
quelle
Wenn nicht das Wasserzeichen die Sichtbarkeit auf den Fokuszustand der Kontrolle abhängig ist, möchten Sie es hängt davon ab , ob der Benutzer einen beliebigen Text eingegeben hat, können Sie John Myczek Antwort aktualisieren (von
OnWatermarkChanged
unten) zuDies ist sinnvoller, wenn Ihr Textfeld beim Anzeigen des Formulars oder bei der Datenbindung an die Text-Eigenschaft automatisch fokussiert wird.
Auch wenn Ihr Wasserzeichen ist immer nur eine Zeichenfolge, und Sie müssen den Stil des Wasserzeichens den Stil der Textbox passen, dann in dem Adorner tun:
quelle
Hier ist mein Ansatz Großartig für MVVM, wo ich auch überprüfe, ob das Textfeld den Fokus hat. Sie können auch einen regulären Auslöser nur für den Textwert verwenden. Der Punkt ist, dass ich nur das Hintergrundbild ändere, wenn sich der Wert ändert:
quelle
Ich beschloss, dies über ein Verhalten zu lösen. Es verwendet eine
Hint
Eigenschaft, um den anzuzeigenden Text zu definieren (kann auch ein Objekt sein, wenn Sie dies bevorzugen) und eineValue
Eigenschaft, um zu bewerten, ob der Hinweis sichtbar sein soll oder nicht.Das Verhalten wird wie folgt deklariert:
Es umschließt das Ziel mit einer eigenen Vorlage und fügt eine Beschriftung hinzu:
Um es zu verwenden, fügen Sie es einfach als Verhalten hinzu und binden Sie Ihre Werte (in meinem Fall füge ich es in eine ControlTemplate ein, daher die Bindung):
Ich würde mich über Feedback freuen, wenn dies als saubere Lösung angesehen wird. Es erfordert keine statischen Wörterbücher und hat daher keinen Speicherverlust.
quelle
Ich habe diesen Weg gefunden, um es sehr schnell und einfach zu machen
Vielleicht kann es jedem helfen, der dies versucht
Quelle: http://www.admindiaries.com/displaying-a-please-select-watermark-type-text-in-a-wpf-combobox/
quelle
quelle
Fügen Sie Ihrem Projekt mahapps.metro hinzu. Fügen Sie dem Fenster ein Textfeld mit dem obigen Code hinzu.
quelle