WPF StringFormat für Etiketteninhalte


76

Ich möchte meinen String formatiert werden verbindlich, Amount is Xwo Xan eine Markierung gebunden ist eine Eigenschaft.

Ich habe viele Beispiele gesehen, aber das Folgende funktioniert nicht:

<Label Content="{Binding Path=MaxLevelofInvestment, 
   StringFormat='Amount is {0}'}" />

Ich habe auch diese Kombinationen ausprobiert:

StringFormat=Amount is {0}
StringFormat='Amount is {}{0}'
StringFormat='Amount is \{0\}'

Ich habe sogar versucht die Bindungseigenschaft des Datentyps zu ändern int, stringund double. Nichts scheint zu funktionieren. Dies ist ein sehr häufiger Anwendungsfall, scheint jedoch nicht unterstützt zu werden.

Antworten:


201

Der Grund, warum dies nicht funktioniert, ist, dass die Label.ContentEigenschaft vom Typ Objectist und Binding.StringFormatnur beim Binden an eine Eigenschaft vom Typ verwendet wird String.

Was passiert ist:

  1. Das Bindingboxt Ihren MaxLevelOfInvestmentWert und speichert die Label.ContentEigenschaft als dezimalen Boxwert.
  2. Das Label-Steuerelement verfügt über eine Vorlage, die a enthält ContentPresenter.
  3. Da ContentTemplatenicht gesetzt ist, ContentPresentersucht nach einem DataTemplatefür den DecimalTyp definierten . Wenn keine gefunden wird, wird eine Standardvorlage verwendet.
  4. Die Standardvorlage, die von den ContentPresenterPresent-Zeichenfolgen mithilfe der ContentStringFormatEigenschaft des Labels verwendet wird .

Zwei Lösungen sind möglich:

  • Verwenden Sie Label.ContentStringFormat anstelle von Binding.StringFormat oder
  • Verwenden Sie eine String-Eigenschaft wie TextBlock.Text anstelle von Label.Content

So verwenden Sie Label.ContentStringFormat:

<Label Content="{Binding Path=MaxLevelofInvestment}" ContentStringFormat="Amount is {0}" />

So verwenden Sie einen TextBlock:

<TextBlock Text="{Binding Path=MaxLevelofInvestment, StringFormat='Amount is {0}'}" />

Hinweis: Der Einfachheit halber habe ich in der obigen Erklärung ein Detail weggelassen: Das verwendet ContentPresentertatsächlich seine eigenen Templateund StringFormatEigenschaften, aber während des Ladens werden diese automatisch an die ContentTemplateund ContentStringFormatEigenschaften des und gebunden Label, sodass es so aussieht, als ob das ContentPresentertatsächlich die LabelEigenschaften des verwendet .


danke für die ausführliche erklärung, jetzt macht es sinn. bis zum WPF-Team, um dies für die Zukunft ordentlich zu machen.
Alles ist

Ich mag Ihre Antwort, würden Sie wissen, wie man 2 Parameter anstelle von nur 1 verwendet? Wirklich Probleme hier (wie TextBlock stringFormat kann mehrere verarbeiten, wenn Trigger usw. verwendet werden).
EricG

Warum müssen Sie in diesem Fall Path = vor Ihre Bindung stellen? Normalerweise könnte ich Content="{Binding MaxLevelofInvestment}"es einfach tun und es funktioniert
einwandfrei

4
Für die Nachwelt: Wenn Sie ein ContentStringFormat mit einem starten {0}, vergessen Sie nicht, es {}davor zu setzen . Also mach esContentStringFormat="{}{0} some text here"
jep

7

Machen Sie eine universelle StringFormatConverter : IValueConverter. Übergeben Sie Ihre Formatzeichenfolge als ConverterParameter.

Label Content="{Binding Amount, Converter={...myConverter}, ConverterParameter='Amount is {0}'"

Machen StringFormatMultiConverter : IMultiValueConverterSie auch, wenn Sie beispielsweise mehr als ein Objekt im Format string benötigen Completed {0} tasks out of {1}.


Ich mag das. Ich kann den Wert der Verwendung sowohl des reinen XAMLAnsatzes als auch des Wertekonverters erkennen.
IAbstract

4

Ich habe es gerade überprüft und aus irgendeinem Grund funktioniert es nicht mit dem Label, wahrscheinlich weil es intern einen ContentPresenter für die Content-Eigenschaft verwendet. Sie können stattdessen einen TextBlock verwenden, und das wird funktionieren. Sie können den folgenden TextBlock-Auszug auch in den Inhalt eines Labels einfügen, wenn Sie Stil, Verhalten usw. erben müssen.

<TextBlock Text="{Binding Path=MaxLevelofInvestment, StringFormat='Amount is \{0\}'} />

1

Versuchen Sie es mit einem Konverter ....

<myconverters:MyConverter x:Key="MyConverter"/>


<Label Content="{Binding Path=MaxLevelofInvestment, Converter={StaticResource MyConverter"} />


public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return String.Format("Amount is {0}", value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

4
Es ist übertrieben. Ich erkläre die Ursache des Problems und präsentiere in meiner Antwort zwei einfache Lösungen.
Ray Burns

Ich bin damit einverstanden, dass dies die Verwendung verbirgt. Ich habe kürzlich ein Projekt geerbt, in dem dieser Ansatz gewählt wurde, und würde Entwicklern den Build in StringFormat vorziehen, anstatt ihre eigenen zu rollen.
Fermin

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.