A vinculação WPF com StringFormat não funciona nas dicas de ferramentas

87

O código a seguir tem uma vinculação simples que vincula o Text do TextBlock denominado MyTextBlock à propriedade Text and ToolTip do TextBox usando exatamente a mesma notação 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>

A associação também usa a propriedade StringFormat introduzida no .NET 3.5 SP1, que está funcionando bem para a propriedade Text acima, mas parece estar quebrada para a dica de ferramenta. O resultado esperado é "It is: Foo Bar", mas quando você passa o mouse sobre o TextBox, a dica de ferramenta mostra apenas o valor de ligação, não o valor formatado da string. Alguma ideia?

Huseyint
fonte
3
Não consegui fazer com que nenhuma das soluções sugeridas abaixo funcionasse, mas esta funcionou: stackoverflow.com/questions/4498649/…
17 de 26 de

Respostas:

156

As dicas de ferramentas no WPF podem conter qualquer coisa, não apenas texto, portanto, fornecem uma propriedade ContentStringFormat para os momentos em que você deseja apenas texto. Você precisará usar a sintaxe expandida, tanto quanto eu sei:

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

Não tenho 100% de certeza sobre a validade da vinculação usando a sintaxe ElementName de uma propriedade aninhada como essa, mas a propriedade ContentStringFormat é o que você está procurando.

Matt Hamilton
fonte
1
Eu vejo, eu pensei que a dica de ferramenta é apenas uma string simples como no Windows Forms. E sim, a sintaxe ElementName, neste caso, não pode acessar o elemento externo.
huseyint
9
Observe que o {} é necessário apenas quando você coloca o {0} no início da string, portanto, você precisa dele para distinguir das outras marcações xaml.
Shimmy Weitzhandler
5
Mente = explodido. Eu acabei de bater nisso e disse "waaaat?"
2
Realmente me surpreendeu que o formato de string não 'simplesmente funciona' quando nenhum conversor é especificado. Eu tive que escrever meu próprio stringformatConverter. MS deixando a bola cair novamente ...
Gusdor 26/11/12
3
StringFormatsó será aplicado quando TargetTypefor o tipo de string. ToolTipO conteúdo é do tipo object.
Johannes Wanzek,
22

Pode ser um bug. Quando você usa uma sintaxe curta para a dica de ferramenta:

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

StringFormat é ignorado, mas quando você usa sintaxe expandida:

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

Funciona como esperado.

MuiBienCarlota
fonte
A resposta mais precisa .. Obrigado!
Amir Mahdi Nassiri
5

Como Matt disse, a dica de ferramenta pode conter qualquer coisa dentro, então para você você pode vincular um TextBox.Text dentro de sua dica de ferramenta.

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

Até você pode empilhar uma grade dentro da dica de ferramenta e fazer o layout de seu texto, se quiser.

Lucas Locatelli
fonte
3

Seu código pode ser tão curto quanto este:

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

Usaremos o fato de que Conversores nunca são ignorados, ao contrário de StringFormat.

Coloque isso em 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();
        }
    }
}

Coloque isso em seu ResourceDictionary.xaml :

<conv:StringFormatConverter x:Key="convStringFormat"/>
Athari
fonte
Embora eu preferisse a resposta principal, o problema do ElementBinding me enganou. Essa resposta funcionou para o meu caso, enquanto os outros não.
Reginald Blue
0

Nessa situação, você pode usar ligação relativa:

<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>
Сергей Игнахин
fonte
-7

O seguinte é uma solução prolixo, mas funciona.

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

Eu preferiria uma sintaxe muito mais simples, algo como o da minha pergunta original.

Huseyint
fonte
1
@Shimmy: "melhor" está nos olhos de quem vê, e não há problema em marcar sua própria pergunta como resposta aceita
Andomar
1
@Shimmy Pior ainda, sua resposta inclui uma piada de '42'.
6
@Andomar, melhor é o que o pessoal decide com os votos, principalmente aqui, é quase a mesma resposta. fazer o ppl responder às suas perguntas e depois copiar suas respostas e ganhar reputação por isso é uma atitude completamente errada.
Shimmy Weitzhandler