I have a case when I need to set default text only for disabled TextBox controls in my WPF application. That is enabled controls may contain empty text, but when control is disabled with empty text there should be displayed binded value e.g. "No data".
Is there any proper way to do this in WPF?
>Solution :
You can use behavior like this:
public enum DisplayDefaultTextMode
{
TextBoxTextEmpty,
TextBoxDisabledAndTextEmpty
}
public class DefaultTextBoxValueBehavior : Behavior<TextBox>
{
public DisplayDefaultTextMode DisplayMode { get; set; } = DisplayDefaultTextMode.TextBoxDisabledAndTextEmpty;
public string DefaultText
{
get => (string)GetValue(DefaultTextProperty);
set => SetValue(DefaultTextProperty, value);
}
public static readonly DependencyProperty DefaultTextProperty =
DependencyProperty.Register(
nameof(DefaultText),
typeof(string),
typeof(DefaultTextBoxValueBehavior),
new PropertyMetadata(string.Empty));
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
AssociatedObject.TextChanged += OnTextChanged;
AssociatedObject.IsEnabledChanged += OnIsEnabledChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnLoaded;
AssociatedObject.TextChanged -= OnTextChanged;
AssociatedObject.IsEnabledChanged -= OnIsEnabledChanged;
}
private void OnLoaded(object sender, RoutedEventArgs e) => SetDefaultTextIfNeeded();
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
if (AssociatedObject.Text?.Length == 0 && e.Changes.Any(c => c.RemovedLength > 0))
{
//ignore since we expect the user to cleare the field for futher input
}
else
SetDefaultTextIfNeeded();
}
private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) => SetDefaultTextIfNeeded();
private void SetDefaultTextIfNeeded()
{
if (CheckShouldSetDefaultText())
SetDefaultText();
}
private bool CheckShouldSetDefaultText()
{
if (DisplayMode == DisplayDefaultTextMode.TextBoxTextEmpty)
return string.IsNullOrEmpty(AssociatedObject.Text);
else
return string.IsNullOrEmpty(AssociatedObject.Text) && !AssociatedObject.IsEnabled;
}
private void SetDefaultText()
{
AssociatedObject.TextChanged -= OnTextChanged;
AssociatedObject.Text = DefaultText;
AssociatedObject.TextChanged += OnTextChanged;
}
}
Usage example:
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<TextBox>
<i:Interaction.Behaviors>
<behaviors:DefaultTextBoxValueBehavior
DisplayMode="TextBoxDisabledAndTextEmpty"
DefaultText="Default text"/>
</i:Interaction.Behaviors>
</TextBox>
N.B! You can define DisplayMode property in the behavior to set up default text appearence. If you set DisplayDefaultTextMode.TextBoxTextEmpty default text will be set if texbox text is null or empty. And if you set DisplayDefaultTextMode.TextBoxDisabledAndTextEmpty defualt text will be set only to the disabled textbox with empty text.
Hope it will be helpful for you.