在 wpf 中的自定义样式上,文本框的文本始终为空

Posted

技术标签:

【中文标题】在 wpf 中的自定义样式上,文本框的文本始终为空【英文标题】:Text of the textbox is always empty on a customized styling in wpf 【发布时间】:2021-09-08 18:30:37 【问题描述】:

嘿,我正在使用 XAML 代码为我的 WPF 应用程序中的文本框设计一种新样式。文本框是文本框和文本块的组合,我使用文本块在文本为空时显示文本框的名称,在填充文本时消失,但是当我运行应用程序并在文本框中填充内容时出现问题似乎它工作正常,但是在后端,当我想访问文本框文本时,即使它已填充,它也是空的!!!! 我是从基地做错了什么还是我错过了一些事情。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="x:Type TextBox"
           x:Key="TextBoxTheme">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="x:Type TextBox">
                    <Border CornerRadius="10"
                            Background="#353340"
                            Width="200"
                            Height="40">
                        <Grid>
                            <Rectangle StrokeThickness="1"/>
                            <TextBox Margin="1" 
                                     Text="TemplateBinding Property=Text"
                                     BorderThickness="0"
                                     Background="Transparent"
                                     VerticalAlignment="Center"
                                     Padding="5"
                                     Foreground="#CFCFCF"
                                     x:Name="textBox"/>
                            <TextBlock IsHitTestVisible="False"
                                       Text="TemplateBinding Name"
                                       VerticalAlignment="Center"
                                       HorizontalAlignment="Left"
                                       Margin="10, 0, 0, 0"
                                       FontSize="11"
                                       Foreground="DarkGray">
                                <TextBlock.Style>
                                    <Style TargetType="x:Type TextBlock">
                                        <Style.Triggers>
                                            <DataTrigger Binding="Binding Text, ElementName=textBox" Value="">
                                                <Setter Property="Visibility" Value="Visible"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                        <Setter Property="Visibility" Value="Hidden"/>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

    </Style>
</ResourceDictionary>

【问题讨论】:

ControlTemplate 中为TextBox 使用TextBox 不是一个好主意。 UserControlControlTemplate 中的内容有关? 【参考方案1】:

您没有给 TextBox 一个区域来显示其内容,而是将它与另一个 TextBox 重叠在上面。 为了显示其内容,TextBox 在模板中查找ScrollViewer x:Name="PART_ContentHost"

试试这样的模板:

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="x:Type TextBox">
                        <Border x:Name="border" BorderBrush="TemplateBinding BorderBrush" BorderThickness="TemplateBinding BorderThickness" Background="TemplateBinding Background" SnapsToDevicePixels="True">
                            <Grid>
                                <TextBlock x:Name="PART_TextBlock" Text="TemplateBinding Name" Visibility="Collapsed"/>
                                <ScrollViewer x:Name="PART_ContentHost"
                                          Focusable="false"
                                          HorizontalScrollBarVisibility="Hidden"
                                          VerticalScrollBarVisibility="Hidden"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Text"
                                         Value="x:Static sys:String.Empty">
                                <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

【讨论】:

【参考方案2】:

如果您检查the documentation for TemplateBinding,您会发现它只是单向RelativeSource 绑定到模板化父级的语法糖,因此您需要做的就是更改您的TextBox 绑定以使其双向:

Text="Binding Path=Text, RelativeSource=RelativeSource TemplatedParent, Mode=TwoWay"

另外,我不同意上面关于这不是一个好主意的评论,WPF 模板系统的全部目的之一是使模板现有控件成为可能,例如用于重新分发库等。也就是说,我认为 Name 不是用于提示文本的最佳属性,如果没有其他原因,就是它不允许空格。更好的解决方案是使用attached property。对于快速而简单的解决方案,还有Tag 属性,您可以随意使用它。

【讨论】:

我认为您对 TempleBinding 的看法是错误的。这个问题已经不止一次被提出了,在网上你可以很容易地找到相关的话题。这种单向绑定是有意进行的,以避免控件模板对控件的逻辑(行为)的影响。在一个正确实现的模板中,不应该有 Mode=TwoWay 绑定到元素属性。模板问题的原因(来自该主题的作者)不同。

以上是关于在 wpf 中的自定义样式上,文本框的文本始终为空的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 WPF 中设置组合框的背景

检查 iOS 8 的自定义键盘中的输入文本是不是为空

自定义 UICollectionViewCell 中的 UILabel 始终为空,无法更新文本

WinForms 文本框的自定义插入符号

黑莓中的自定义文本框

位置样式为绝对时滚动时的文本框定位问题