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?

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

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)


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 >

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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.