WPF在TextBox中混合使用绑定和固定文本

9
我有以下代码来显示客户的年龄。
<TextBox x:Name="txtClientAge" Text="{Binding Path=ClientAge}" />

然而,我不仅想显示数字,还想在其前面加上文本“年龄”,在其后面加上文本“岁”,以便实际上变成“年龄36岁”。

我可以使用水平StackPanel和3个文本框来实现这一点,但我是否错过了更简单的方法?


您是否希望“age”和“yrs”部分可编辑?即用户是否允许在文本框中完整输入“age 40 yrs”(或者仅仅是“40”),并且正确解析? - Pavel Minaev
无论如何,如果您的应用程序中只有一个这样的文本框(即不需要重复使用),那么StackPanel + 2 TextBlocks + TextBox解决方案将是最简单的。 - Pavel Minaev
仅用于只读,无需更新。 - Mitch
4个回答

9
假设你不需要可编辑的年龄值,在WPF 4.0中,Run的Text属性将是可绑定的。除非你正在使用预发布版本,否则这可能对你现在没有帮助,但你将能够执行以下操作:
<TextBlock x:Name="txtClientAge" >
    <Run Text="Age "/><Run Text="{Binding Path=ClientAge}"/><Run Text=" Yrs"/>
</TextBlock>

更新:这里有另一种替代格式化字符串解决方案的方法,虽然不是很好看(实际上有点糟糕),但是它可以正常工作。将以下转换器用于绑定(假设ClientAge属性是int类型):

public class AgeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          System.Globalization.CultureInfo culture)
    {
        string age = value.ToString();
        return "Age " + age + " years";
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                              System.Globalization.CultureInfo culture)
    {
        string age = value as string;
        return Int32.Parse(age.Replace("Age ", " ").Replace(" years", ""));
    }
}

谢谢Simon,这正是我在寻找的东西,但正如你所说,它还没有完全到来!也许我现在不得不采取冗长的方法,直到WPF 4.0与我们同在。 - Mitch
不错的侧面思考啊,伙计。我目前很喜欢使用转换器来处理各种事情,所以你的方法真的很吸引人。谢谢! - Mitch
是的,ConvertBack 是我不喜欢的部分,但由于这是只读情况,所以不会成为问题。 - Simon Fox

6

这是一个相当古老的问题,但我认为这是当前最佳解决方案(如果您想编辑文本)。

您可以在嵌套的Textbox中使用TextBlock中的InlineUIContainer来完成它。

注意:我使用了BaselineAlignment="Center"来对齐组件。您还可以根据需要向TextBox添加正负边距。此外,我将TextBox的边框设置为透明,以使其看起来像是TextBlock的一部分,即使它是可编辑和可选择的。

<TextBlock Foreground="SteelBlue">
    <Run Text="Package Barcode:" FontWeight="Bold" BaselineAlignment="Center"/>
    <InlineUIContainer BaselineAlignment="Center">
        <TextBox Margin="2,0,0,0" Foreground="Gray" Text="{Binding BarcodeNumber}" BorderThickness="0" Padding="0"/>
    </InlineUIContainer>
</TextBlock>

1
是的,我意识到最初提问者希望“年龄”只读 - 但这是对所提出问题的回答 :-) - Simon_Weaver
这是一个相当老的答案。 - Simon_Weaver

5
你可以在你绑定的类中创建一个属性来创建你想要显示的文本字符串。
还有一种方法是使用StringFormat:
<textblock text="{Binding Path=mydate, StringFormat=d}"/>

您可以将常量嵌入格式化字符串中进行劫持。
我更喜欢使用属性方法。

3
这基本上是将您的模型修改为视图感知 - 从设计角度来看,这是一个非常糟糕的想法。 - Pavel Minaev
1
+1 for StringFormat。同意@Pavel的观点 - 不要创建一个包含此文本的属性。 - Andy
2
如果你真的想做得好,那么这个文本也不应该在视图中。它需要在资源区中,根据当前文化设置由表示层选择。这就是为什么我的所有东西都来自演示者属性。 - Jay

1
这就像之前的回答一样 - (但它们都是用Texblocks...所以这里是一个Textbox版本),我也想展示Multibinding方法。要让Texbox做你想要的事情,你可以使用以下代码:
<TextBox>
 <TextBox.Text>
   <MultiBinding StringFormat="Age {0} yrs and {1} months">
     <Binding Path="Years" />
     <Binding Path="Months" />
   </MultiBinding>
 </TextBox.Text>
</TextBox>

如果您希望使文本可选,以便用户可以复制代码,则此功能可能非常有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接