如何使格式化的TextBlock宽度数据绑定可本地化?

Nik*_*iki 13 wpf binding

在我的WPF应用程序中,我想显示如下所示的内容:

用户Bob已于22:17退出.

"Bob"和"22:17"是数据绑定值.

显而易见的方法是使用StackPanel带有多个TextBlock子节点的子节点,其中一些绑定数据:

<StackPanel Orientation="Horizontal">
   <TextBlock Text="The user"/>
   <TextBlock Text="{Binding Path=Username}" TextBlock.FontWeight="Bold" />
   <TextBlock Text="has logged off at"/>
   <TextBlock Text="{Binding Path=LogoffTime}" TextBlock.FontWeight="Bold" />
</StackPanel/>
Run Code Online (Sandbox Code Playgroud)

这有效,但很难看.该程序应该被本地化为不同的语言,并且具有"用户"和"已注销"的单独字符串是本地化灾难的接收者.

理想情况下,我想做这样的事情:

<TextBlock>
     <TextBlock.Text>
         <MultiBinding StringFormat="{}The user <Bold>{0}</Bold> has logged off at <Bold>{1}</Bold>">
             <Binding Path="Username" />
             <Binding Path="LogoffTime" />
         </MultiBinding>
</TextBlock>
Run Code Online (Sandbox Code Playgroud)

所以译者会看到一个完整的句子The user <Bold>{0}</Bold> has logged off at <Bold>{1}</Bold>.但这当然不起作用.

这必须是一个常见的问题,对此有什么正确的解决方案?

Aar*_*ver 12

我看到的问题是你想要一个String具有不同UI存在的单个String.

一种选择可能是不需要粗体,只需将单个String放在Resources.resx文件中即可.这String将随后在其中的属性来引用TextBlock绑定到,返回的值根据需要; {0}和{1}适用的地方.

另一种选择可能是返回一组Run要保留的值TextBlock.你不能绑定到Run3.5中的开箱即用,但我相信你可以在4.

            <TextBlock>
                  <Run Text="The user "/><Run FontWeight="Bold" Text="{Binding User}"/><Run Text="has logged at "/><Run FontWeight="Bold" Text="{Binding LogoffTime}"/>
            </TextBlock>
Run Code Online (Sandbox Code Playgroud)

最后一个选项可以在这里找到并涉及创建一个更动态的Run概念方法,允许您绑定您的值,然后将它们绑定到一个String.


Rac*_*hel 4

我以前从未尝试过做这样的事情,但如果必须的话,我可能会尝试使用一个转换器,该转换器接受 MultiBinding 并将其分解并返回各个部分的 StackPanel

例如,绑定将类似于:

<Label>
     <Label.Content>
             <MultiBinding Converter={StaticResource TextWithBoldParametersConverter}>
                 <Binding Source="The user {0} has logged off at {1}" />
                 <Binding Path="Username" />
                 <Binding Path="LogoffTime" />
             </MultiBinding>
    </Label.Content>
</Label>
Run Code Online (Sandbox Code Playgroud)

转换器会做类似的事情

public class TextWithBoldParametersConverter: IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // Create a StackPanel to hold the content
        // Set StackPanel's Orientation to Horizontal 

        // Take values[0] and split it by the {X} tags

        // Go through array of values parts and create a TextBlock object for each part
            // If the part is an {X} piece, use values[X+1] for Text and make TextBlock bold
            // Add TextBlock to StackPanel

        // return StackPanel
    }
}
Run Code Online (Sandbox Code Playgroud)