La liaison WPF avec StringFormat ne fonctionne pas sur les info-bulles

87

Le code suivant a une liaison simple qui lie le texte du TextBlock nommé MyTextBlock à la propriété Text et ToolTip de TextBox en utilisant exactement la même notation de liaison:

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

La liaison utilise également la propriété StringFormat introduite avec .NET 3.5 SP1 qui fonctionne correctement pour la propriété Text ci-dessus mais semble être interrompue pour l'info-bulle. Le résultat attendu est "C'est: Foo Bar" mais lorsque vous survolez la zone de texte, l'info-bulle affiche uniquement la valeur de liaison, pas la valeur au format chaîne. Des idées?

Huseyint
la source
3
Je n'ai pas réussi à faire fonctionner l'une des solutions suggérées ci-dessous, mais celle-ci a fonctionné: stackoverflow.com/questions/4498649/...
17 du 26

Réponses:

156

Les info-bulles dans WPF peuvent contenir n'importe quoi, pas seulement du texte, elles fournissent donc une propriété ContentStringFormat pour les moments où vous voulez simplement du texte. Vous devrez utiliser la syntaxe développée pour autant que je sache:

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

Je ne suis pas sûr à 100% de la validité de la liaison à l'aide de la syntaxe ElementName à partir d'une propriété imbriquée comme celle-ci, mais la propriété ContentStringFormat est ce que vous recherchez.

Matt Hamilton
la source
1
Je vois, je pensais que ToolTip n'était qu'une simple chaîne comme dans Windows Forms. Et oui, la syntaxe ElementName dans ce cas ne peut pas accéder à l'élément externe.
huseyint
9
Notez que {} n'est requis que lorsque vous placez {0} au début de la chaîne, vous en avez donc besoin pour le distinguer des autres balises xaml.
Shimmy Weitzhandler
5
Esprit = soufflé. Je viens de frapper ça et c'était comme "waaaat?"
2
Cela m'a vraiment convaincu que le format de chaîne ne «fonctionne pas seulement» lorsqu'aucun convertisseur n'est spécifié. J'ai dû écrire mon propre stringformatConverter. MS
lâche à
3
StringFormatne sera appliqué que lorsque le TargetTypetype de chaîne est. ToolTipLe contenu est de type object.
Johannes Wanzek
22

Cela pourrait être un bug. Lorsque vous utilisez une syntaxe courte pour l'info-bulle:

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

StringFormat est ignoré mais lorsque vous utilisez une syntaxe développée:

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

Cela fonctionne comme prévu.

MuiBienCarlota
la source
La réponse la plus précise .. Merci!
Amir Mahdi Nassiri
5

Comme Matt l'a dit, l'info-bulle peut contenir n'importe quoi à l'intérieur, vous pouvez donc lier un TextBox.Text à l'intérieur de votre info-bulle.

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

Même vous pouvez empiler une grille à l'intérieur de l'info-bulle et mettre en page votre texte si vous le souhaitez.

Lucas Locatelli
la source
3

Votre code peut être aussi court que ceci:

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

Nous utiliserons le fait que les convertisseurs ne sont jamais ignorés, contrairement à StringFormat.

Mettez ceci dans 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();
        }
    }
}

Mettez ceci dans votre ResourceDictionary.xaml :

<conv:StringFormatConverter x:Key="convStringFormat"/>
Athari
la source
Alors que j'aurais préféré la première réponse, le problème ElementBinding m'a fait trébucher. Cette réponse a fonctionné pour mon cas là où les autres n'ont pas fonctionné.
Reginald Blue
0

Dans cette situation, vous pouvez utiliser la liaison relative:

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

Ce qui suit est une solution verbeuse mais cela fonctionne.

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

Je préférerais une syntaxe beaucoup plus simple, quelque chose comme celle de ma question initiale.

Huseyint
la source
1
@Shimmy: "mieux" est dans l'œil du spectateur, et c'est bien de marquer votre propre question comme la réponse acceptée
Andomar
1
@Shimmy Pire encore, sa réponse comprend une blague «42».
6
@Andomar, mieux c'est ce que les gens décident avec leurs votes, aussi particulièrement ici, c'est presque la même réponse. obliger les personnes à répondre à vos questions puis à copier leurs réponses et à gagner en réputation car c'est une attitude complètement fausse.
Shimmy Weitzhandler