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

发布于 2025-02-11 06:11:56 字数 132 浏览 1 评论 0原文

当我需要在WPF应用程序中使用禁用> TextBox 控件时,我只需要设置默认文本。这是启用的控件可能包含空文本,但是当禁用控件使用空文本禁用时,应显示binden bended值,例如“无数据”。

在WPF中有什么正确的方法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

落花随流水 2025-02-18 06:11:56

您可以使用这样的行为:

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;
    }
}

用法示例:

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

<TextBox>
    <i:Interaction.Behaviors>
        <behaviors:DefaultTextBoxValueBehavior
            DisplayMode="TextBoxDisabledAndTextEmpty"
            DefaultText="Default text"/>
        </i:Interaction.Behaviors>
</TextBox>

NB!您可以在行为中定义displayMode属性,以设置默认文本显示。如果您设置displayDefaultTextMode.textboxtextempty如果TexBox文本为空或空,则将设置默认文本。如果您设置displayDefaultTextMode.textboxdisabledandtextempty Defualt Text将仅设置为带有空文本的禁用文本框。

希望这对您有帮助。

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.

红墙和绿瓦 2025-02-18 06:11:56

您不需要转换器,可以在纯XAML中完成。

首先,将光标放在文本框上,在属性窗格中选择其他 - &gt;模板 - &GT;转换为新资源。这将模板删除您的控件,从而为您提供一些编辑。只需将part_contenthost元素更改为包含您默认文本的文本块:

<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>

现在只需使用样式将该控制模板应用于禁用控件时:

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

现在,当您将类似的内容放入XAML中时,则现在

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

。 ..您得到这个:

”在此处输入图像描述”

You don't need a converter for this, it can be done in pure XAML.

First, place the cursor over a TextBox, and in the Properties pane select 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:

<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:

<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:

<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:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文