TextBlockのスタックを使用する代わりに、文字列を連結します


88

WPFItemsControlにCustomerオブジェクトのリストを表示したいと思います。このためのDataTemplateを作成しました:

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

したがって、基本的に必要なのは、NUMBER-NAMEを含む単純なリスト(チェックボックス付き)です。バインディング部分で番号と名前を直接連結する方法はありませんか?

回答:


171

StringFormatプロパティ(.NET 3.5 SP1)があり、おそらく使用できます。そして、便利なWPFバインディングチートシートはここにあります。それでも問題が解決しない場合は、オブジェクトに対して独自のValueConverterまたはカスタムプロパティをいつでも作成できます。

チェックしただけで、StringFormatをマルチバインディングで使用できます。あなたの場合、コードは次のようになります。

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

フォーマット文字列をスペースで開始する必要がありました。そうしないと、Visual Studioはビルドされませんが、それを回避する方法が見つかると思います:)

編集
パーサーが{0}実際のバインディングとして扱われないようにするには、StringFormatにスペースが必要です。他の選択肢:

<!-- 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
スペースの代わりに{}を使用できます。例:StringFormat = "{} {0}-{1}"
Bryan Anderson

6
バックスラッシュで中括弧をエスケープすることもできます:<MultiBinding StringFormat = "\ {0 \}-\ {1 \}">
hughdbrown 2009

また、終了するTextBlockが欠落しているため、コメントを要約すると、次のようになります。<TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0}-{1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </ MultiBinding> </TextBlock.Text> </ TextBlock>
TJKjaer 2010

「名前」が空の場合でも「番号」を表示したい場合は@ PiRX-どうすればよいですか?
dasDas 2015

@DasDas残念ながら、私はWPFを数年間使用していないため、あなたの質問に答えることができません。作業していないものをどれだけ早く忘れてしまうかはおかしいです。
PiRX 2015

64

動的な値を静的なテキストと連結する場合は、次のことを試してください。

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

ディスプレイ:234-334-5566(SSN)


1
TextBlockLeftStyleの内容は何ですか?
itsho 2013年

これは、テキストブロックを左に揃える必要があるカスタムスタイルです。ここでは意味がありません。
redskull 2013年

1
これは、バインディングを文字列と連結するための最良のソリューションです
Devid

8

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

バインド可能な実行を使用することもできます。特にテキストの書式設定(色、フォントの太さなど)を追加したい場合に便利です。

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

ここだ元のクラスは:
ここにいくつかの追加の改善があります。
そして、それはすべて1つのコードに含まれています。

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 ...}" />?利点を説明できますか?
FelixKeil19年

1
変わりはない; この回答が書かれた10年前、RunはTextプロパティのバインディングをサポートしていませんでした。
josh21 1219
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.