WPF绑定与StringFormat在工具提示上无法使用

92

以下代码使用简单绑定,将名为 MyTextBlock 的 TextBlock 的 Text 和 ToolTip 属性绑定到 TextBox 的 Text 属性,使用完全相同的 Binding 表示法:

<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似乎出现了问题。预期结果是“It is: Foo Bar”,但当您将光标悬停在文本框上时,ToolTip仅显示绑定值,而不是经过格式化的字符串值。有什么想法吗?


4
我无法使下面建议的两个解决方案起作用,但这个可以:https://dev59.com/u2855IYBdhLWcg3wKw9Y - 17 of 26
6个回答

169

WPF中的工具提示可以包含任何内容,不仅仅是文本。如果你只需要文本,那么可以使用ContentStringFormat属性。据我所知,你需要使用扩展语法:

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

我不确定从嵌套属性使用ElementName语法绑定的有效性,但是ContentStringFormat属性是你要找的。


10
请注意,只有当你将{0}放在字符串开头时才需要使用{},因此需要使用它来区分其他XAML标记。 - Shimmy Weitzhandler
5
大脑=炸裂。我刚刚看到这个,就像是“哇?!” - user1228
2
真的让我很恼火的是,当没有指定转换器时,stringformat不能“正常工作”。我不得不编写自己的stringformatConverter。微软又一次失误了... - Gusdor
1
“ElementName” 无法在此处使用,似乎我尝试使用“RelativeSource”(带有“AncestorType”)也不行。那么,如何将其绑定到任何有意义的内容呢? - O. R. Mapper
5
只有当 TargetType 是字符串类型时,才会应用 StringFormatToolTip 内容的类型为 object - Johannes Wanzek
显示剩余2条评论

27

可能是一个错误。 当您使用提示的短语法时:

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

它的表现符合预期。


2
最准确的答案。谢谢! - Amir Mahdi Nassiri
编译时缺少 WhatEverYouWant 后面的逗号。 - Norbert Hüthmayr

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 问题让我困扰了。这个答案适用于我的情况,而其他答案则不行。 - Reginald Blue

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>

-8
以下是一个冗长的解决方案,但它可以工作。
<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
1
@Shimmy 更糟糕的是,他的回答包括一个“42”的笑话。 - user1228
6
@Andomar,更好的决定应该由大家投票决定,尤其是在这种情况下,这几乎就是同样的答案。让人们回答你的问题,然后复制他们的答案并因此获得声望是完全错误的态度。 - Shimmy Weitzhandler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接