Прив'язка WPF за допомогою StringFormat не працює на підказках


87

Наступний код має просте прив'язування, яке пов'язує текст TextBlock з ім'ям MyTextBlock із властивістю TextBox Text і ToolTip, використовуючи ті самі позначення 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>

Прив'язка також використовує властивість StringFormat, представлену в .NET 3.5 SP1, яка чудово працює для вищевказаної властивості Text, але, схоже, не працює для підказки. Очікуваний результат - "Це: Foo Bar", але коли ви наводите курсор на TextBox, підказка показує лише значення прив'язки, а не відформатоване значення рядка. Будь-які ідеї?


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.
Shimmy Weitzhandler

5
Розум = подутий. Я просто вдарив це, і було як "waaaat?"

2
Мене дуже засмутило, що формат рядків не просто працює, коли не вказано конвертер. Мені довелося написати власний stringformatConverter. MS знову скинув м'яч ...
Гусдор,

3
StringFormatзастосовуватиметься лише тоді, коли TargetTypeє тип рядка. 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>

Це працює, як очікувалося.


Найточніша відповідь .. Дякую!
Амір Махді Нассірі,

5

Як сказав Метт, ToolTip може містити все, що завгодно, щоб ви могли прив'язати TextBox.Text всередині ToolTip.

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

-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

1
@Shimmy Ще гірше, що його відповідь включає жарт "42".

6
@Andomar, краще, що люди вирішують своїми голосами, також тут особливо, це майже однакова відповідь. змусити людей відповідати на ваші запитання, а потім копіювати їхні відповіді та здобувати репутацію, це абсолютно неправильне ставлення.
Shimmy Weitzhandler
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.