Concatenar strings em vez de usar uma pilha de TextBlocks

91

Eu quero mostrar uma lista de objetos do cliente em um WPF ItemsControl. Criei um DataTemplate para isso:

    <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>

Então, o que eu quero basicamente é uma lista simples (com caixas de seleção) que contém NUMBER - NAME. Não há uma maneira de conciliar o número e o nome diretamente na parte Binding?

Gerrie Schenck
fonte

Respostas:

175

Existe a propriedade StringFormat (no .NET 3.5 SP1), que provavelmente você pode usar. E um truque de cheat WPF útil pode ser encontrado aqui . Se não ajudar, você sempre pode escrever seu próprio ValueConverter ou propriedade personalizada para o seu objeto.

Apenas verificado, você pode usar StringFormat com multibinding. No seu caso, o código será algo como este:

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

Tive que começar a formatar string com espaço, caso contrário, o Visual Studio não criaria, mas acho que você encontrará uma maneira de contornar isso :)

Editar
O espaço é necessário no StringFormat para evitar que o analisador seja tratado {0}como uma ligação real. Outras alternativas:

<!-- 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
fonte
29
Em vez do espaço, você pode usar {}, por exemplo, StringFormat = "{} {0} - {1}"
Bryan Anderson
6
Você também pode escapar das chaves com barras invertidas: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown
Além disso, o TextBlock de fechamento está faltando, para resumir os comentários: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer
@PiRX se eu quiser mostrar 'número' mesmo se 'nome' estiver vazio - como faço isso?
DasDas
@DasDas, infelizmente, não poderei ajudar com sua pergunta, pois não trabalho com o WPF há vários anos. É engraçado como você esquece rápido as coisas com as quais não está mais trabalhando.
PiRX de
66

Caso você queira concatenar um valor dinâmico com um texto estático, tente o seguinte:

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

Monitores : 234-334-5566 (SSN)

caveira Vermelha
fonte
1
Qual é o conteúdo de TextBlockLeftStyle?
itsho
É um estilo personalizado que tenho que alinhar o bloco de texto à esquerda. Não tem nenhum significado aqui.
redskull
1
Esta é a melhor solução para concatenar uma ligação com uma string
Devid,
9

Veja o seguinte exemplo que usei em meu código usando a classe 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
fonte
3

Você também pode usar uma execução vinculável. Coisas úteis, especialmente se alguém quiser adicionar alguma formatação de texto (cores, espessura da fonte, etc.).

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

Aqui está uma aula original:
Aqui estão algumas melhorias adicionais.
E tudo isso em um único código:

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
fonte
1
<Run Text = "{Binding ...}" />? Você pode explicar as vantagens?
Felix Keil
1
Sem diferença; Executar não suportava vinculações na propriedade Text 10 anos atrás, quando esta resposta foi escrita!
josh2112