Формат рядка WPF на вмісті етикетки


77

Я хочу відформатувати прив'язку мого рядка як Amount is Xде Xвластивість, прив'язана до мітки.

Я бачив багато прикладів, але наступне не працює:

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

Я також спробував ці комбінації:

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

Я навіть спробував змінити тип властивості прив'язки на int, stringі double. Здається, нічого не працює. Це дуже поширений варіант використання, але, схоже, не підтримується.

Відповіді:


205

Причина, по якій це не працює, полягає в тому, що Label.Contentвластивість має тип Objectі Binding.StringFormatвикористовується лише при прив’язці до властивості типу String.

Те, що відбувається:

  1. Це Bindingбоксує ваше MaxLevelOfInvestmentзначення та зберігає його Label.Contentвластивість у вигляді десяткового значення в коробці.
  2. Елемент керування Label має шаблон, який містить ContentPresenter.
  3. Оскільки ContentTemplateне встановлено, ContentPresenterшукає DataTemplateвизначений для Decimalтипу. Коли він не знаходить жодного, він використовує шаблон за замовчуванням.
  4. Шаблон за замовчуванням, який використовується ContentPresenterпредставленими рядками за допомогою ContentStringFormatвластивості мітки .

Можливі два рішення:

  • Використовуйте Label.ContentStringFormat замість Binding.StringFormat або
  • Використовуйте властивість String, наприклад TextBlock.Text, замість Label.Content

Ось як використовувати Label.ContentStringFormat:

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

Ось як використовувати TextBlock:

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

Примітка: Для простоти я опустив одну деталі в наведеному вище поясненні: на ContentPresenterсамому ділі використовує своє власне Templateі StringFormatвластивість, але при завантаженні вони автоматично шаблони прив'язані до ContentTemplateі ContentStringFormatвластивостями Label, так що здається , ніби ContentPresenterнасправді , використовуючи Labelвластивості «s .


дякую за детальне пояснення, тепер це має сенс. до команди WPF, щоб зробити це акуратним на майбутнє.
Все має значення

Мені подобається ваша відповідь. Чи знаєте ви, як використовувати 2 параметри замість лише 1? Тут справді важко (наприклад, TextBlock stringFormat може обробляти декілька при використанні тригерів тощо).
EricG

Чому саме в цьому випадку вам потрібно поставити Path = перед вашим прив'язуванням? як правило, я міг просто робити, Content="{Binding MaxLevelofInvestment}"і це чудово працює ...
MistaGoustan

6
Для нащадків: якщо ви починаєте ContentStringFormat з {0}, не забудьте поставити {}перед ним. Так що ContentStringFormat="{}{0} some text here"
встигайте

7

Зробіть універсал StringFormatConverter : IValueConverter. Передайте рядок формату як ConverterParameter.

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

Крім того , переконайтеся , StringFormatMultiConverter : IMultiValueConverterколи вам потрібно більше , ніж один об'єкт в рядку формату, наприклад, Completed {0} tasks out of {1}.


Мені подобається це. Я бачу цінність використання як чистого XAMLпідходу, так і перетворювача вартості.
I Абстрактний 02

4

Я щойно перевірив, і з якихось причин він не працює з етикеткою, можливо, тому, що він використовує ContentPresenter для властивості Content внутрішньо. Ви можете використовувати TextBlock замість цього, і це буде працювати. Ви також можете помістити витяг TextBlock нижче у вміст мітки, якщо вам потрібно успадкувати стиль, поведінку тощо.

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

1

Спробуйте скористатися перетворювачем ....

<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
Це надмірно. Я пояснюю причину проблеми та пропоную у своїй відповіді два простих рішення.
Рей Бернс,

Я погоджуюсь, що це приховує використання, нещодавно я успадкував проект, де був застосований такий підхід, і я набагато віддав би перевагу розробникам використовувати збірку в StringFormat, ніж прокручувати власні.
Фермін

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.