在 XAML 中设置 TextBox 的宽度,以便它能够显示 x 位数字

Eug*_*sky 5 wpf xaml

我想设置 WPF 文本框的宽度,以便它有足够的空间容纳任何 5 位 TCP 端口号。它不应该更大,也不应该动态调整大小,即 Width="Auto" 不是我想要的。

我正在寻找一种通用的方法,即尊重所使用的字体的方法,并且我不想在字体或任何其他可能改变像素宽度 5 的情况下摆弄像素精确的宽度值数字 - 已更改。

我想通过 MeasureString 在代码中实现是可能的(虽然有点尴尬),但这在 XAML 中可能吗?

Mik*_*son 2

好吧,它可能并不完美,但这是一个可能的解决方案。

创建一个ControlTemplate包含所需属性CharacterLengthGhostString依赖属性的属性。

public class DynamicTextBox : TextBox
{
    public int CharacterLength
    {
        get { return (int)GetValue(CharacterLengthProperty); }
        set { SetValue(CharacterLengthProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CharacterLength.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CharacterLengthProperty =
        DependencyProperty.Register("CharacterLength", typeof(int), typeof(DynamicTextBox), new PropertyMetadata(5, new PropertyChangedCallback(CharacterLengthChanged)));

    public string GhostString
    {
        get { return (string)GetValue(GhostStringProperty); }
        private set { SetValue(GhostStringProperty, value); }
    }

    // Using a DependencyProperty as the backing store for GhostString.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty GhostStringProperty =
        DependencyProperty.Register("GhostString", typeof(string), typeof(DynamicTextBox), new PropertyMetadata("#####"));

    static DynamicTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicTextBox), new FrameworkPropertyMetadata(typeof(DynamicTextBox)));
    }

    private static void CharacterLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DynamicTextBox textbox = d as DynamicTextBox;

        string ghost = string.Empty;

        for (int i = 0; i < textbox.CharacterLength; i++)
            ghost += "#";

        textbox.GhostString = ghost;
    }
}
Run Code Online (Sandbox Code Playgroud)

每当CharacterLength属性发生变化时,GhostString属性就会被重新计算,很快你就会看到它的神奇之处。

为这个新控件设置Style和。ControlTemplate

<Style TargetType="{x:Type local:DynamicTextBox}"
       BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DynamicTextBox}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <TextBlock Text="{TemplateBinding GhostString}"
                                   Visibility="Hidden"
                                   Margin="3,0"/>

                        <ScrollViewer Margin="0"
                                  x:Name="PART_ContentHost" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

GhostString属性被放置在Hidden TextBlock内部,这意味着宽度被渲染,但文本是不可见的,它TextBox无论如何都被放置在后面。

您可以像这样使用该控件:

<Controls:DynamicTextBox CharacterLength="12" HorizontalAlignment="Left"/>
    <Controls:DynamicTextBox CharacterLength="6" HorizontalAlignment="Left"/>
    <Controls:DynamicTextBox CharacterLength="2" HorizontalAlignment="Left"/>
Run Code Online (Sandbox Code Playgroud)

注意:我将 Horizo​​ntalAlignment 放在那里只是为了强制宽度折叠。

结果如下:

StackPanel 内的文本框

它并不完美,但这无疑是一个开始。如果您想进一步限制 的宽度TextBox,我相当确定您可以在ControlTemplate.