简体   繁体   English

仅为 WPF 中禁用的文本框设置默认文本

[英]Set default text only for disabled textbox in WPF

I have a case when I need to set default text only for disabled TextBox controls in my WPF application.我有一个案例,我需要为我的 WPF 应用程序中禁用的TextBox控件设置默认文本。 That is enabled controls may contain empty text, but when control is disabled with empty text there should be displayed binded value eg "No data".启用的控件可能包含空文本,但是当控件被空文本禁用时,应该显示绑定值,例如“无数据”。

Is there any proper way to do this in WPF?在 WPF 中有没有合适的方法来做到这一点?

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>

NB!注意! You can define DisplayMode property in the behavior to set up default text appearence.您可以在行为中定义DisplayMode属性以设置默认文本外观。 If you set DisplayDefaultTextMode.TextBoxTextEmpty default text will be set if texbox text is null or empty.如果您设置DisplayDefaultTextMode.TextBoxTextEmpty ,如果 texbox 文本为空或为空,则将设置默认文本。 And if you set DisplayDefaultTextMode.TextBoxDisabledAndTextEmpty defualt text will be set only to the disabled textbox with empty text.如果您设置DisplayDefaultTextMode.TextBoxDisabledAndTextEmpty默认文本将仅设置为带有空文本的禁用文本框。

Hope it will be helpful for you.希望对您有所帮助。

You don't need a converter for this, it can be done in pure XAML.您不需要转换器,它可以在纯 XAML 中完成。

First, place the cursor over a TextBox, and in the Properties pane select Miscellaneous -> Template -> Convert to New Resource.首先,将光标放在一个 TextBox 上,然后在 Properties 窗格中选择 Miscellaneous -> Template -> Convert to New Resource。 That will template out your control, giving you something to edit.这将模板化你的控制,给你一些东西来编辑。 Simply change the PART_ContentHost element to a TextBlock containing your default text:只需将PART_ContentHost元素更改为包含默认文本的 TextBlock:

<SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
<SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
<ControlTemplate x:Key="TextBoxTemplate1" TargetType="{x:Type TextBoxBase}">
    <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
        <!--<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>-->
        <TextBlock Text="Nothing to see here!" />
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocused" Value="true">
            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

And now just use a style to apply that ControlTemplate to whenever the control is disabled:现在只需使用一种样式将 ControlTemplate 应用于控件被禁用时:

<Style TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="TextBox.IsEnabled" Value="false">
            <Setter Property="Template" Value="{DynamicResource TextBoxTemplate1}" />
        </Trigger>
    </Style.Triggers>
</Style>

So now when you put something like this in your XAML:所以现在当你在你的 XAML 中加入这样的东西时:

<StackPanel Orientation="Vertical">
    <TextBox Width="150" Text="This textbox is enabled" />
    <TextBox Width="150" Text="This textbox is disabled" IsEnabled="False" />
</StackPanel>

...you get this: ...你得到这个:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM