Bir TextBlock yığını kullanmak yerine dizeleri birleştirin


91

WPF ItemsControl'de Müşteri nesnelerinin bir listesini göstermek istiyorum. Bunun için bir DataTemplate oluşturdum:

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

Yani temelde istediğim, SAYI - ADI içeren basit bir liste (onay kutuları olan). Numarayı ve adı doğrudan Ciltleme kısmında birleştirebileceğim bir yol yok mu?

Yanıtlar:


175

Muhtemelen kullanabileceğiniz StringFormat özelliği (.NET 3.5 SP1'de) vardır. Ve yararlı WPF bağlama hile kılıfı burada bulunabilir . Yardımcı olmazsa, her zaman kendi ValueConverter'ınızı veya nesneniz için özel özelliğinizi yazabilirsiniz.

Sadece kontrol edildiğinde, StringFormat'ı çoklu bağlama ile kullanabilirsiniz. Durumunuzda kod şöyle bir şey olacaktır:

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

Biçim dizesini boşlukla başlatmak zorunda kaldım, aksi takdirde Visual Studio oluşturulmazdı, ancak bunun üstesinden gelmenin bir yolunu bulacağınızı düşünüyorum :)

Düzenleme
Ayrıştırıcının {0}gerçek bir bağlama olarak işlem görmesini engellemek için StringFormat'ta boşluk gereklidir . Diğer alternatifler:

<!-- 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
Boşluk yerine {} kullanabilirsiniz, örneğin StringFormat = "{} {0} - {1}"
— Bryan Anderson

6
Ayraçlardan ters eğik çizgilerle de kaçabilirsiniz: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
— hughdbrown

Ayrıca, kapanış TextBlock da eksik, bu nedenle yorumları özetlemek için: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
— TJKjaer

@PiRX 'isim' boş olsa bile 'numara' göstermek istersem bunu nasıl yaparım?
— DasDas

@DasDas, WPF ile birkaç yıldır çalışmadığım için maalesef sorunuza yardımcı olamayacağım. Artık çalışmadığınız şeyleri ne kadar hızlı unutmanız çok komik.
— PiRX

66

Dinamik bir değeri statik bir metinle birleştirmek istemeniz durumunda şunu deneyin:

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

Ekranlar : 234-334-5566 (SSN)


1
TextBlockLeftStyle'ın içeriği nedir?
— itsho

Metin bloğunu sola hizalamam gereken özel bir stil. Burada önemi yok.
— redskull

1
Bu, bir bağlamayı bir dizeyle birleştirmenin en iyi çözümü
— Devid

9

Run sınıfını kullanarak kodumda kullandığım aşağıdaki örneğe bakın:

        <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

Bağlanabilir bir çalıştırma da kullanabilirsiniz. Yararlı şeyler, özellikle bazı metin biçimlendirmeleri (renkler, yazı tipi ağırlığı vb.)

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

İşte orijinal bir sınıf:
İşte bazı ek iyileştirmeler.
Ve bunların hepsi tek parça kodda:

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 ...}" />? Avantajları açıklayabilir misin?
— Felix Keil

1
Fark yok; Çalıştırma, 10 yıl önce bu yanıt yazıldığında Text özelliğindeki bağlamaları desteklemiyordu!
— josh2112
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.