Concatena le stringhe invece di usare una pila di TextBlock


88

Voglio mostrare un elenco di oggetti Cliente in un ItemsControl di WPF. Ho creato un DataTemplate per questo:

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

Quindi quello che voglio fondamentalmente è un semplice elenco (con caselle di controllo) che contenga NUMERO - NOME. Non c'è un modo in cui posso concatenare il numero e il nome direttamente nella parte Binding?

Risposte:


171

C'è la proprietà StringFormat (in .NET 3.5 SP1), che probabilmente puoi usare. E l'utile cheat sheat di associazione WPF può essere trovato qui . Se non aiuta, puoi sempre scrivere il tuo ValueConverter o una proprietà personalizzata per il tuo oggetto.

Appena spuntato, puoi usare StringFormat con multibinding. Nel tuo caso il codice sarà qualcosa del genere:

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

Ho dovuto iniziare la stringa di formato con lo spazio, altrimenti Visual Studio non sarebbe stato costruito, ma penso che troverai il modo di aggirarlo :)

Modifica
Lo spazio è necessario in StringFormat per impedire al parser di trattare {0}come un'associazione effettiva. Altre alternative:

<!-- 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}">

29
Al posto dello spazio puoi utilizzare {}, ad es. StringFormat = "{} {0} - {1}"
Bryan Anderson

6
Puoi anche eseguire l'escape delle parentesi graffe con le barre rovesciate: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown

Inoltre, manca il TextBlock di chiusura, quindi per riassumere i commenti: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer

@PiRX se voglio mostrare "numero" anche se "nome" è vuoto, come posso farlo?
DasDas

@DasDas purtroppo non sarò in grado di aiutarti con la tua domanda poiché non lavoro con WPF da diversi anni. È divertente quanto velocemente dimentichi le cose su cui non lavori più.
PiRX

64

Nel caso in cui desideri concatenare un valore dinamico con un testo statico, prova questo:

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

Visualizzazioni : 234-334-5566 (SSN)


1
Qual è il contenuto di TextBlockLeftStyle?
itsho

È uno stile personalizzato che devo allineare il blocco di testo a sinistra. Non ha significato qui.
Redskull

1
Questa è la soluzione migliore per concatenare un'associazione con una stringa
Devid

8

Guarda il seguente esempio che ho usato nel mio codice usando la 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 >

3

È inoltre possibile utilizzare una corsa associabile. Cose utili, soprattutto se si desidera aggiungere un po 'di formattazione del testo (colori, spessore del carattere ecc.).

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

Ecco una classe originale:
ecco alcuni miglioramenti aggiuntivi.
E questo è tutto in un pezzo di codice:

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);
        }
    }

1
<Run Text = "{Binding ...}" />? Puoi spiegare i vantaggi?
Felix Keil

1
Nessuna differenza; Run non supportava le associazioni sulla proprietà Text 10 anni fa quando è stata scritta questa risposta!
josh2112
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.