Powiązanie WPF z StringFormat nie działa w etykietkach narzędzi


87

Poniższy kod zawiera proste powiązanie, które wiąże tekst elementu TextBlock o nazwie MyTextBlock z właściwością TextBox i etykietkę narzędzia przy użyciu dokładnie tej samej notacji 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>

Powiązanie używa również właściwości StringFormat wprowadzonej w .NET 3.5 SP1, która działa dobrze w przypadku powyższej właściwości Text, ale wydaje się być uszkodzona w przypadku etykietki narzędzia. Oczekiwany wynik to „It is: Foo Bar”, ale po najechaniu kursorem na TextBox, ToolTip pokazuje tylko wartość powiązania, a nie wartość sformatowaną jako ciąg. Jakieś pomysły?


3
Nie udało mi się uruchomić żadnego z sugerowanych poniżej rozwiązań, ale to zadziałało: stackoverflow.com/questions/4498649/ ...
17 z 26

Odpowiedzi:


156

Etykietki narzędzi w WPF mogą zawierać wszystko, nie tylko tekst, więc zawierają właściwość ContentStringFormat dla czasów, w których potrzebny jest tylko tekst. O ile wiem, będziesz musiał użyć rozszerzonej składni:

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

Nie jestem w 100% pewien co do ważności powiązania przy użyciu składni ElementName z zagnieżdżonej właściwości, takiej jak ta, ale właściwość ContentStringFormat jest tym, czego szukasz.


1
Rozumiem, pomyślałem, że ToolTip to zwykły ciąg, jak w Windows Forms. I tak, składnia ElementName w tym przypadku nie może uzyskać dostępu do elementu zewnętrznego.
huseyint

9
Zauważ, że {} jest wymagany tylko wtedy, gdy umieścisz {0} na początku ciągu, więc potrzebujesz go do odróżnienia od innych znaczników xaml.
Shimmy Weitzhandler,

5
Umysł = oszołomiony. Po prostu uderzyłem w to i powiedziałem "waaaat?"

2
Naprawdę zdałem sobie sprawę, że format string nie „działa”, gdy nie określono konwertera. Musiałem napisać własny stringformatConverter. MS ponownie upuszcza piłkę ...
Gusdor

3
StringFormatzostanie zastosowane tylko wtedy, gdy TargetTypejest to typ łańcucha. ToolTipTreść jest typu object.
Johannes Wanzek

22

To może być błąd. Gdy używasz krótkiej składni dla podpowiedzi:

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

StringFormat jest ignorowany, ale gdy używasz rozszerzonej składni:

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

Działa zgodnie z oczekiwaniami.


Najdokładniejsza odpowiedź… Dzięki!
Amir Mahdi Nassiri

5

Jak powiedział Matt, ToolTip może zawierać wszystko w środku, więc możesz powiązać TextBox.Text wewnątrz swojej 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>

Nawet możesz ułożyć siatkę wewnątrz etykiety narzędzi i ułożyć tekst, jeśli chcesz.


3

Twój kod może być tak krótki, jak ten:

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

Skorzystamy z faktu, że konwertery nigdy nie są ignorowane, w przeciwieństwie do StringFormat.

Umieść to w 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();
        }
    }
}

Umieść to w swoim ResourceDictionary.xaml :

<conv:StringFormatConverter x:Key="convStringFormat"/>

Chociaż wolałbym najlepszą odpowiedź, problem ElementBinding mnie zaskoczył. Ta odpowiedź zadziałała w moim przypadku, podczas gdy inne nie.
Reginald Blue

0

W tej sytuacji możesz użyć względnego wiązania:

<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

Poniższe rozwiązanie jest rozwlekłe, ale działa.

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

Wolałbym znacznie prostszą składnię, podobną do tej z mojego pierwotnego pytania.


1
@Shimmy: „lepiej” jest w oku patrzącego i można oznaczyć własne pytanie jako zaakceptowaną odpowiedź
Andomar,

1
@Shimmy Co gorsza, jego odpowiedź zawiera żart „42”.

6
@Andomar, lepsze jest to, co ludzie decydują swoimi głosami, szczególnie tutaj, to prawie ta sama odpowiedź. zmuszanie ludzi do udzielania odpowiedzi na pytania, a następnie kopiowanie ich i zdobywanie reputacji, ponieważ jest to całkowicie błędne nastawienie.
Shimmy Weitzhandler
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.