Связывание WPF с StringFormat не работает во всплывающих подсказках

87

Следующий код имеет простую привязку, которая связывает текст TextBlock с именем MyTextBlock со свойством TextBox и свойством 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>

Привязка также использует свойство StringFormat, представленное в .NET 3.5 SP1, которое отлично работает для указанного выше свойства Text, но, похоже, не работает для всплывающей подсказки. Ожидаемый результат - «Это: панель Foo», но когда вы наводите курсор на TextBox, всплывающая подсказка показывает только значение привязки, а не значение в строковом формате. Любые идеи?

Huseyint
источник
3
Мне не удалось заставить работать ни одно из предложенных ниже решений, но это помогло: stackoverflow.com/questions/4498649/…
17 из 26

Ответы:

156

Всплывающие подсказки в WPF могут содержать что угодно, а не только текст, поэтому они предоставляют свойство ContentStringFormat для тех случаев, когда вам нужен только текст. Насколько я знаю, вам нужно будет использовать расширенный синтаксис:

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

Я не уверен на 100% в правильности привязки с использованием синтаксиса ElementName из такого вложенного свойства, но свойство ContentStringFormat - это то, что вы ищете.

Мэтт Гамильтон
источник
1
Понятно, я думал, что ToolTip - это обычная строка, как в Windows Forms. И да, синтаксис ElementName в этом случае не может получить доступ к внешнему элементу.
huseyint
9
Обратите внимание, что {} требуется только тогда, когда вы помещаете {0} в начало строки, поэтому вам нужно, чтобы он отличался от других разметок xaml.
Шимми Вайцхандлер,
5
Разум = взорван. Я просто нажал на это и подумал: «Уаааат?»
2
Меня очень огорчило то, что строковый формат не «просто работает», когда не указан конвертер. Мне пришлось написать свой собственный stringformatConverter. МС снова уронил мяч ...
Gusdor
3
StringFormatбудет применяться только тогда, когда TargetTypeтип строки is. ToolTipКонтент имеет тип object.
Йоханнес Ванзек
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>

Работает как положено.

MuiBienCarlota
источник
Самый точный ответ .. Спасибо!
Амир Махди Насири
5

Как сказал Мэтт, всплывающая подсказка может содержать что угодно внутри, поэтому для вас вы можете привязать 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>

Я бы предпочел гораздо более простой синтаксис, похожий на тот, что был в моем исходном вопросе.

Huseyint
источник
1
@Shimmy: «лучше» в глазах смотрящего, и можно отметить свой вопрос как принятый ответ
Andomar
1
@Shimmy Хуже того, в его ответе есть шутка про 42.
6
@Andomar, лучше люди решают своими голосами, особенно здесь, это почти тот же ответ. заставлять людей отвечать на ваши вопросы, а затем копировать их ответы и завоевывать репутацию, поскольку это совершенно неправильное отношение.
Шимми Вайцхандлер