如何在WPF的TextBlock中在句子中间插入绑定?

11

我正在寻找类似以下的东西:

<TextBlock
    Grid.Column="1"
    Text="Welcome, {Binding UserName}!" />

当然,这实际上会向用户显示文本"{Binding UserName}"而不是解码它,但我知道你可以在ASP.NET中做到这一点,所以我希望有办法在WPF中使其工作。

我已经意识到我可以使用IValueConverter...如果可能的话,我正在寻找纯粹在标记中完成的方法。

编辑:

基于@Matt Hamilton的最佳解决方案,我尝试将两个值绑定到相同的TextBlock中,使用了MultiBinding。非常完美地解决了问题:

<TextBlock
    Style="{StaticResource TextBlock_ValueStyle}"
    Grid.Column="1">
    <TextBlock.Text>
        <MultiBinding
            StringFormat="{}Attempts: {0:G} of {1:G}">
            <Binding
                Path="AttemptNumber" />
            <Binding
                Path="AttemptCount" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

这将产生:尝试次数:1/4(假设AttemptNumber = 1AttemptCount = 4)。

我还发现了这个链接对于确定在冒号后放置哪些格式很有帮助:

http://msdn.microsoft.com/en-us/library/fbxft59x.aspx

5个回答

17
你可以在.NET 3.5 SP1中使用StringFormat绑定属性:
<TextBlock Text="{Binding UserName,StringFormat='Welcome, \{0\}!'}" />

需要注意,在字符串格式化时需要用反斜杠转义花括号。

更新:是的,也支持多个值:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="Welcome, {0} {1}!">
            <Binding Path="FirstName" />
            <Binding Path="LastName" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

哇,那很好。不过,顺序有点奇怪,因为它与通常的 [string]::Format 完全相反。 - Joey
漂亮!这让我想到另一个问题:是否可以有多个绑定值,或者仅限于一个?谢谢。 - devuxer
哎呀 - 你在我更新答案的时候做了那个!好吧! :) - Matt Hamilton
@Johannes 如果你喜欢的话,你可以像使用String.Format一样对它进行排序:Text="{Binding StringFormat='...',Path=UserName" - Matt Hamilton
@Matt:哈哈,我猜多举几个例子也无妨。有些大括号转义的规则我还没完全掌握。请注意,在我的例子中,我在StringFormat的开头使用了{}。在你的原始示例中,你使用了\{\}。然后你在第二个示例中根本不需要转义。此外,直到我添加:G(“通用”格式)之前,它才拒绝我的整数绑定。除了这些怪异之处,StringFormat有了一个新的粉丝。 - devuxer

4
最佳的方法是使用Runs...
<TextBlock>
    <Run Text="Welcome"/>
    <Run Text="{Binding UserName}"/>
    <Run Text="!"/>
</TextBlock>

2

这是将文本和控件混合的最简单方法。

<TextBlock>Welcome, <TextBlock Text="{Binding UserName}"/>!</TextBlock>

您可以内联样式的按钮或其他控件。


0

到目前为止,我还不知道有什么解决方案可以完全按照您所描述的方式实现。但是,您可以使用多个文本块作为解决方法来拼凑您的句子:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Welcome, "/>
    <TextBlock Text="{Binding UserName}"/>
    <TextBlock Text="!"/>
</StackPanel>

这是我迄今为止使用的方法,虽然输入麻烦,但似乎是最简单的解决方案。但是一旦需要国际化,由于明显的原因,它就不可行了。


我以前用过 StackPanel 来连接属性-值对(例如,“状态:成功”),但我有点担心使用它来连接句子的不同部分,因为我认为自然文本间距可能无法保留(即,在 TextBlocks 之间会有比同一 TextBlock 中的单词之间更大的间隔)。如果这不是问题,那么这是一个很好的解决方案。 - devuxer
到目前为止,我没有注意到额外的空间。但是字距很可能不起作用,因为自动连字等等。基本上,你会将文本分成不同的运行,并且我怀疑高级排版不能在这些运行之间工作。但对于一些项目来说,国际化部分是非常重要的,我尽可能避免连接字符串和变量或使用非定位格式字符串。有时候像这样的快速而肮脏的解决方案会存活下来 :-) - Joey

0

看看这个库"WPFix"。它允许用户在XAML中编写lambda表达式。我没有在生产代码中使用它,只在演示代码中使用过。我能够获取一个窗体的宽度,将其除以二,并将该值绑定到一个控件上。通常,您需要创建一个转换器类,就像您所描述的那样。这个库可能是你正在寻找的东西:

http://www.fikrimvar.net/lestirelim/?p=15


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