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?


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.


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.


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.


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

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>

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


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.