String gabungan alih-alih menggunakan tumpukan TextBlocks

91

Saya ingin menampilkan daftar objek Pelanggan di WPF ItemsControl. Saya telah membuat DataTemplate untuk ini:

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

Jadi yang saya inginkan pada dasarnya adalah daftar sederhana (dengan kotak centang) yang berisi NOMOR - NAMA. Apakah tidak ada cara di mana saya dapat menggabungkan nomor dan nama secara langsung di bagian Binding?

Gerrie Schenck
sumber

Jawaban:

175

Ada properti StringFormat (dalam .NET 3.5 SP1), yang mungkin bisa Anda gunakan. Dan cheat sheat pengikat WPF yang berguna dapat ditemukan di sini . Jika tidak membantu, Anda selalu dapat menulis ValueConverter atau properti kustom Anda sendiri untuk objek Anda.

Centang saja, Anda dapat menggunakan StringFormat dengan multibinding. Dalam kasus Anda, kode akan menjadi seperti ini:

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

Saya harus mulai memformat string dengan spasi, jika tidak, Visual Studio tidak akan dibangun, tetapi saya pikir Anda akan menemukan cara untuk mengatasinya :)

Sunting
Ruang diperlukan dalam StringFormat untuk menjaga agar parser tidak diperlakukan {0}sebagai pengikatan sebenarnya. Alternatif lain:

<!-- 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
sumber
29
Alih-alih spasi yang bisa Anda gunakan {}, misalnya StringFormat = "{} {0} - {1}"
Bryan Anderson
6
Anda juga dapat melepaskan tanda kurung kurawal dengan garis miring terbalik: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown
Selain itu, TextBlock penutup tidak ada, jadi untuk meringkas komentar: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer
@PiRX jika saya ingin menampilkan 'nomor' meskipun 'nama' kosong- bagaimana cara melakukannya?
DasDas
@DasDas sayangnya saya tidak dapat membantu dengan pertanyaan Anda karena saya belum bekerja dengan WPF selama beberapa tahun. Lucu sekali betapa cepatnya Anda melupakan hal-hal yang tidak Anda kerjakan lagi.
PiRX
66

Jika Anda ingin menggabungkan nilai dinamis dengan teks statis, coba ini:

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

Menampilkan : 234-334-5566 (SSN)

tengkorak merah
sumber
1
Apa konten TextBlockLeftStyle?
itsho
Ini adalah gaya kustom saya harus menyelaraskan textblock ke kiri. Tidak ada artinya di sini.
redskull
1
Ini adalah solusi terbaik untuk menggabungkan pengikatan dengan string
Devid
9

Lihat contoh berikut yang saya gunakan dalam kode saya menggunakan kelas 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 >
pengguna3262530
sumber
3

Anda juga dapat menggunakan lari yang dapat diikat. Hal-hal yang berguna, terutama jika seseorang ingin menambahkan beberapa format teks (warna, fontweight, dll.).

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

Ini kelas aslinya:
Berikut beberapa peningkatan tambahan.
Dan itu semua dalam satu kode:

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
sumber
1
<Jalankan Text = "{Binding ...}" />? Bisakah Anda menjelaskan keuntungannya?
Felix Keil
1
Tidak ada perbedaan; Run tidak mendukung binding pada properti Text 10 tahun yang lalu saat jawaban ini ditulis!
josh2112