StringFormatを使用したWPFバインディングはツールチップでは機能しません


87

次のコードには、MyTextBlockという名前のTextBlockのTextを、まったく同じBinding表記を使用してTextBoxのTextおよびToolTipプロパティにバインドする単純なバインディングがあります。

<StackPanel>
    <TextBlock x:Name="MyTextBlock">Foo Bar</TextBlock>
    <TextBox    Text="{Binding ElementName=MyTextBlock, Path=Text, StringFormat='It is: \{0\}'}"
             ToolTip="{Binding ElementName=MyTextBlock, Path=Text, StringFormat='It is: \{0\}'}" />
</StackPanel>

バインディングでは、.NET 3.5 SP1導入されStringFormatプロパティも使用されます。これは、上記のTextプロパティでは正常に機能しますが、ToolTipでは壊れているようです。期待される結果は「Itis:Foo Bar」ですが、TextBoxにカーソルを合わせると、ツールチップには文字列形式の値ではなく、バインド値のみが表示されます。何か案は?


3
私はどちらかの作業に以下の提案ソリューションの取得することができませんでしたが、この1つはやった:stackoverflow.com/questions/4498649/...
26の17

回答:


156

WPFのツールチップにはテキストだけでなく何でも含めることができるため、テキストが必要なときにContentStringFormatプロパティを提供します。私の知る限り、拡張構文を使用する必要があります。

<TextBox ...>
  <TextBox.ToolTip>
    <ToolTip 
      Content="{Binding ElementName=myTextBlock,Path=Text}"
      ContentStringFormat="{}It is: {0}"
      />
  </TextBox.ToolTip>
</TextBox>

そのようなネストされたプロパティからのElementName構文を使用したバインディングの有効性については、100%確信がありませんが、ContentStringFormatプロパティがあなたが探しているものです。


1
なるほど、ToolTipはWindowsフォームのように単なる文字列だと思いました。はい、この場合のElementName構文は外部要素にアクセスできません。
huseyint 2008年

9
{}は、文字列の先頭に{0}を配置する場合にのみ必要であるため、他のxamlマークアップと区別するために必要であることに注意してください。
シミーワイツハンドラー2009

5
心=吹き飛ばされた。これを叩いただけで「わぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁぁ」

2
コンバーターが指定されていない場合、stringformatが「正しく機能しない」ことは本当に私を驚かせました。独自のstringformatConverterを作成する必要がありました。再びボールをドロップするMS ...
Gusdor

3
StringFormatTargetTypeisタイプの文字列の場合にのみ適用されます。ToolTipコンテンツはタイプobjectです。
Johannes Wanzek 2014年

22

バグの可能性があります。ツールチップに短い構文を使用する場合:

<TextBox ToolTip="{Binding WhatEverYouWant StringFormat='It is: \{0\}'}" />

StringFormatは無視されますが、拡張構文を使用する場合:

<TextBox Text="text">
   <TextBox.ToolTip>
      <TextBlock Text="{Binding WhatEverYouWant StringFormat='It is: \{0\}'}"/>
   </TextBox.ToolTip>
</TextBox>

期待どおりに動作します。


最も正確な答え..ありがとう!
Amir Mahdi Nassiri 2018年

5

Mattが言ったように、ToolTipには何でも含めることができるので、ToolTip内にTextBox.Textをバインドできます。

<StackPanel>
    <TextBlock x:Name="MyTextBlock">Foo Bar</TextBlock>
    <TextBox Text="{Binding ElementName=MyTextBlock, Path=Text, StringFormat='It is: \{0\}'}">
        <TextBox.ToolTip>
            <TextBlock>
                <TextBlock.Text>
                    <Binding ElementName=MyTextBlock Path="Text" StringFormat="It is: {0}" />
                </TextBlock.Text>
            </TextBlock>
        </TextBox.ToolTip>
    </TextBox>
</StackPanel>

ツールチップ内にグリッドを積み重ねて、必要に応じてテキストをレイアウトすることもできます。


3

コードは次のように短くすることができます。

<TextBlock ToolTip="{Binding PrideLands.YearsTillSimbaReturns,
    Converter={StaticResource convStringFormat},
    ConverterParameter='Rejoice! Just {0} years left!'}" Text="Hakuna Matata"/>

StringFormatとは異なり、コンバーターは決して無視されないという事実を使用します。

これをStringFormatConverter.csに入れます

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace TLKiaWOL
{
    [ValueConversion (typeof(object), typeof(string))]
    public class StringFormatConverter : IValueConverter
    {
        public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (ReferenceEquals(value, DependencyProperty.UnsetValue))
                return DependencyProperty.UnsetValue;
            return string.Format(culture, (string)parameter, value);
        }

        public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

これをResourceDictionary.xamlに入れます:

<conv:StringFormatConverter x:Key="convStringFormat"/>

私は一番上の答えを好むでしょうが、ElementBindingの問題は私をつまずかせました。この答えは、他の人がうまくいかなかった私の場合にはうまくいきました。
レジナルドブルー

0

この状況では、相対バインディングを使用できます。

<StackPanel>
    <TextBlock x:Name="MyTextBlock">Foo Bar</TextBlock>
    <TextBox Text="{Binding ElementName=MyTextBlock, Path=Text, StringFormat='It is: \{0\}'}"
             ToolTip="{Binding Text, RelativeSource={RelativeSource Self}}" />
</StackPanel>

-7

以下は簡単な解決策ですが、機能します。

<StackPanel>
  <TextBox Text="{Binding Path=., StringFormat='The answer is: {0}'}">
    <TextBox.DataContext>
      <sys:Int32>42</sys:Int32>
    </TextBox.DataContext>
    <TextBox.ToolTip>
      <ToolTip Content="{Binding}" ContentStringFormat="{}The answer is: {0}" />
    </TextBox.ToolTip>
  </TextBox>
</StackPanel>

私は、元の質問のような、はるかに単純な構文を好みます。


1
@Shimmy:「より良い」は見る人の目にあり、あなた自身の質問に受け入れられた答えをマークするのは大丈夫です
Andomar 2009

1
@Shimmyさらに悪いことに、彼の答えには「42」のジョークが含まれています。

6
@Andomar、人々が投票で決めるのは良いことですが、ここでも特にそうです、それはほとんど同じ答えです。pplにあなたの質問に答えさせ、次に彼らの答えをコピーして評判を得ることは完全に間違った態度です。
シミーワイツハンドラー2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.