El enlace de WPF con StringFormat no funciona en la información sobre herramientas

87

El siguiente código tiene un enlace simple que enlaza el texto del TextBlock llamado MyTextBlock a la propiedad Text and ToolTip de TextBox usando exactamente la misma notación de enlace:

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

El enlace también usa la propiedad StringFormat introducida con .NET 3.5 SP1 que funciona bien para la propiedad Text anterior pero parece estar rota para la información sobre herramientas. El resultado esperado es "Es: Foo Bar", pero cuando pasa el cursor sobre el TextBox, la información sobre herramientas muestra solo el valor de enlace, no el valor con formato de cadena. ¿Algunas ideas?

huseyint
fuente
3
No pude hacer funcionar ninguna de las soluciones sugeridas a continuación, pero esta sí lo hizo: stackoverflow.com/questions/4498649/…
17 de 26 de

Respuestas:

156

La información sobre herramientas en WPF puede contener cualquier cosa, no solo texto, por lo que proporcionan una propiedad ContentStringFormat para las veces que solo desea texto. Deberá usar la sintaxis ampliada hasta donde yo sé:

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

No estoy 100% seguro de la validez del enlace usando la sintaxis ElementName de una propiedad anidada como esa, pero la propiedad ContentStringFormat es lo que está buscando.

Matt Hamilton
fuente
1
Ya veo, pensé que ToolTip es solo una cadena simple como en Windows Forms. Y sí, la sintaxis de ElementName en este caso no puede acceder al elemento externo.
huseyint
9
Tenga en cuenta que el {} es obligatorio solo cuando coloca el {0} al principio de la cadena, por lo que lo necesita para distinguirlo de las otras marcas de xaml.
Shimmy Weitzhandler
5
Mente = soplado. Acabo de presionar esto y dije "¿waaaat?"
2
Realmente me fastidió que el formato de cadena no 'simplemente funcione' cuando no se especifica ningún convertidor. Tuve que escribir mi propio stringformatConverter. MS deja caer la pelota de nuevo ...
Gusdor
3
StringFormatsolo se aplicará cuando el TargetTypetipo de cadena sea. ToolTipEl contenido es de tipo object.
Johannes Wanzek
22

Podría ser un error. Cuando usa una sintaxis corta para la información sobre herramientas:

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

StringFormat se ignora pero cuando usa sintaxis expandida:

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

Funciona como se esperaba.

MuiBienCarlota
fuente
La respuesta más acertada .. ¡Gracias!
Amir Mahdi Nassiri
5

Como Matt dijo, la información sobre herramientas puede contener cualquier cosa en su interior, por lo que puede vincular un TextBox.Text dentro de su información sobre herramientas.

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

Incluso puede apilar una cuadrícula dentro de la información sobre herramientas y diseñar su texto si lo desea.

Lucas Locatelli
fuente
3

Tu código puede ser tan corto como esto:

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

Usaremos el hecho de que los convertidores nunca se ignoran, a diferencia de StringFormat.

Pon esto en 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();
        }
    }
}

Pon esto en tu ResourceDictionary.xaml :

<conv:StringFormatConverter x:Key="convStringFormat"/>
Athari
fuente
Si bien hubiera preferido la respuesta principal, el problema de ElementBinding me hizo tropezar. Esta respuesta funcionó para mi caso donde los demás no.
Reginald Blue
0

En esta situación, puede utilizar el enlace relativo:

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

La siguiente es una solución prolija pero 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>

Preferiría una sintaxis mucho más simple, algo como la de mi pregunta original.

huseyint
fuente
1
@Shimmy: "mejor" está en el ojo del espectador, y está bien marcar su propia pregunta como la respuesta aceptada
Andomar
1
@Shimmy Peor aún, su respuesta incluye una broma del '42'.
6
@Andomar, mejor es lo que la gente decida con sus votos, también en particular aquí, es casi la misma respuesta. hacer que las personas contesten sus preguntas, luego copien sus respuestas y ganen reputación por ello es una actitud completamente incorrecta.
Shimmy Weitzhandler