Concatenar cadenas en lugar de usar una pila de TextBlocks


88

Quiero mostrar una lista de objetos Customer en WPF ItemsControl. Creé un DataTemplate para esto:

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

Entonces, lo que quiero básicamente es una lista simple (con casillas de verificación) que contenga NUMBER - NAME. ¿No hay alguna forma en la que pueda concatizar el número y el nombre directamente en la parte de enlace?

Respuestas:


171

Existe la propiedad StringFormat (en .NET 3.5 SP1), que probablemente pueda usar. Y la útil funda de trucos de enlace WPF se puede encontrar aquí . Si no ayuda, siempre puede escribir su propio ValueConverter o propiedad personalizada para su objeto.

Recién verificado, puede usar StringFormat con multibinding. En su caso, el código será algo como esto:

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

Tuve que comenzar a formatear la cadena con espacio, de lo contrario Visual Studio no se compilaría, pero creo que encontrará la manera de evitarlo :)

Editar
El espacio es necesario en StringFormat para evitar que el analizador se trate {0}como un enlace real. Otras 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}">

29
En lugar del espacio, puede usar {}, por ejemplo, StringFormat = "{} {0} - {1}"
Bryan Anderson

6
También puede escapar de las llaves con barras invertidas: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown

Además, falta el TextBlock de cierre, así que para resumir los comentarios: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer

@PiRX si quiero mostrar 'número' incluso si 'nombre' está vacío, ¿cómo lo hago?
DasDas

@DasDas desafortunadamente no podré ayudar con su pregunta ya que no he trabajado con WPF durante varios años. Es curioso lo rápido que olvidas cosas con las que ya no estás trabajando.
PiRX

64

En caso de que desee concatizar un valor dinámico con un texto estático, intente esto:

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

Pantallas : 234-334-5566 (SSN)


1
¿Cuál es el contenido de TextBlockLeftStyle?
itsho

Es un estilo personalizado que tengo que alinear el bloque de texto a la izquierda. No tiene ningún significado aquí.
redskull

1
Esta es la mejor solución para concatenar un enlace con una cadena
Devid

8

Vea el siguiente ejemplo que usé en mi código usando la clase Ejecutar:

        <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

También puede utilizar una ejecución enlazable. Cosas útiles, especialmente si se quiere agregar algún formato de texto (colores, tamaño de fuente, etc.).

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

Aquí hay una clase original:
aquí hay algunas mejoras adicionales.
Y eso es todo en una sola pieza de 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);
        }
    }

1
<Run Text = "{Binding ...}" />? ¿Puede explicar las ventajas?
Felix Keil

1
Ninguna diferencia; Run no admitía enlaces en la propiedad Text hace 10 años cuando se escribió esta respuesta.
josh2112
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.