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.