Объединение строк вместо использования стека TextBlocks

88

Я хочу показать список объектов Customer в WPF ItemsControl. Я создал для этого DataTemplate:

    <DataTemplate DataType="{x:Type myNameSpace:Customer}">
        <StackPanel Orientation="Horizontal" Margin="10">
            <CheckBox"></CheckBox>
            <TextBlock Text="{Binding Path=Number}"></TextBlock>
            <TextBlock Text=" - "></TextBlock>
            <TextBlock Text="{Binding Path=Name}"></TextBlock>
        </StackPanel>
    </DataTemplate>

Итак, в основном я хочу простой список (с флажками), содержащий НОМЕР - ИМЯ. Разве нет способа, которым я могу связать номер и имя непосредственно в части привязки?

Герри Шенк
источник

Ответы:

171

Существует свойство StringFormat (в .NET 3.5 SP1), которое вы, вероятно, сможете использовать. И полезный чит-код привязки WPF можно найти здесь . Если это не помогает, вы всегда можете написать свой собственный ValueConverter или настраиваемое свойство для вашего объекта.

Только что проверил, вы можете использовать StringFormat с несколькими привязками. В вашем случае код будет примерно таким:

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat=" {0} - {1}">
        <Binding Path="Number"/>
        <Binding Path="Name"/>
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

Строку формата мне пришлось начинать с пробела, иначе Visual Studio не собрала бы, но я думаю, вы найдете способ обойти это :)

Изменить
. Пространство необходимо в StringFormat, чтобы синтаксический анализатор не воспринимал его {0}как фактическую привязку. Другие альтернативы:

<!-- use a space before the first format -->
<MultiBinding StringFormat=" {0} - {1}">

<!-- escape the formats -->
<MultiBinding StringFormat="\{0\} - \{1\}">

<!-- use {} before the first format -->
<MultiBinding StringFormat="{}{0} - {1}">
PiRX
источник
29
Вместо пробела вы можете использовать {}, например StringFormat = "{} {0} - {1}"
Брайан Андерсон,
6
Вы также можете экранировать фигурные скобки с помощью обратной косой черты: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown
Кроме того, отсутствует закрывающий TextBlock, поэтому, чтобы подвести итог комментариев: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer
@PiRX, если я хочу показать «номер», даже если «имя» пусто - как мне это сделать?
DasDas
@DasDas, к сожалению, я не смогу помочь с вашим вопросом, так как я не работал с WPF несколько лет. Забавно, как быстро ты забываешь то, с чем больше не работаешь.
PiRX
64

Если вы хотите объединить динамическое значение со статическим текстом, попробуйте следующее:

<TextBlock Text="{Binding IndividualSSN, StringFormat= '\{0\} (SSN)'}"/>

Дисплеи : 234-334-5566 (SSN)

Красный Череп
источник
1
Каково содержимое TextBlockLeftStyle?
itsho 02
Это собственный стиль, который мне нужно выровнять по левому краю. Здесь это не имеет значения.
redskull 07
1
Это лучшее решение для объединения привязки со строкой
Devid
8

См. Следующий пример, который я использовал в своем коде с помощью класса Run:

        <TextBlock x:Name="..." Width="..." Height="..."
            <Run Text="Area="/>
            <Run Text="{Binding ...}"/>
            <Run Text="sq.mm"/>
            <LineBreak/>
            <Run Text="Min Diameter="/>
            <Run Text="{Binding...}"/>
            <LineBreak/>
            <Run Text="Max Diameter="/>
            <Run Text="{Binding...}"/>
        </TextBlock >
user3262530
источник
3

Вы также можете использовать привязанный бег. Полезно, особенно если нужно добавить форматирование текста (цвета, размер шрифта и т. Д.).

<TextBlock>
   <something:BindableRun BoundText="{Binding Number}"/>
   <Run Text=" - "/>
   <something:BindableRun BoundText="{Binding Name}"/>
</TextBlock>

Вот оригинальный класс:
Вот некоторые дополнительные улучшения.
И все это в одном фрагменте кода:

public class BindableRun : Run
    {
        public static readonly DependencyProperty BoundTextProperty = DependencyProperty.Register("BoundText", typeof(string), typeof(BindableRun), new PropertyMetadata(new PropertyChangedCallback(BindableRun.onBoundTextChanged)));

        private static void onBoundTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Run)d).Text = (string)e.NewValue;
        }

        public String BoundText
        {
            get { return (string)GetValue(BoundTextProperty); }
            set { SetValue(BoundTextProperty, value); }
        }

        public BindableRun()
            : base()
        {
            Binding b = new Binding("DataContext");
            b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1);
            this.SetBinding(DataContextProperty, b);
        }
    }
cz_dl
источник
1
<Run Text = "{Binding ...}" />? Вы можете объяснить преимущества?
Феликс Кейл
1
Нет разницы; 10 лет назад, когда был написан этот ответ, Run не поддерживал привязки к свойству Text!
josh2112