Используйте StringFormat для добавления строки в привязку WPF XAML

125

У меня есть приложение WPF 4, содержащее TextBlock, который имеет одностороннюю привязку к целочисленному значению (в данном случае - температуре в градусах Цельсия). XAML выглядит так:

<TextBlock x:Name="textBlockTemperature">
        <Run Text="{Binding CelsiusTemp, Mode=OneWay}"/></TextBlock>

Это отлично подходит для отображения фактического значения температуры, но я хотел бы отформатировать это значение так, чтобы оно включало ° C, а не просто число (30 ° C вместо 30). Я читал о StringFormat и видел несколько таких общих примеров:

// format the bound value as a currency
<TextBlock Text="{Binding Amount, StringFormat={}{0:C}}" />

и

// preface the bound value with a string and format it as a currency
<TextBlock Text="{Binding Amount, StringFormat=Amount: {0:C}}"/>

К сожалению, ни один из примеров, которые я видел, не добавлял строку к привязанному значению, как я пытаюсь это сделать. Я уверен, что это должно быть что-то простое, но мне не удалось его найти. Может ли кто-нибудь объяснить мне, как это сделать?

bmt22033
источник

Ответы:

218

Ваш первый пример - это то, что вам нужно:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Рид Копси
источник
20
Почему в строковом формате в xaml начало пусто {}?
Jonesopolis
6
@Jonesopolis Это есть в документации, но если ваша строка формата начинается с a {, она предоставляет механизм для выхода, поскольку {}уже имеет значение в xaml.
Рид Копси,
5
Я не вижу, где в документации объясняется ведущий {}.
Эрик
5
@Eric Как и большая часть документации, это воняет - они демонстрируют это, но не объясняют.
Рид Копси
19
вот документация таинственного {}: msdn.microsoft.com/en-us/library/ms744986.aspx
Jotrius
107

Вот альтернатива, которая хорошо работает для удобочитаемости, если у вас есть привязка в середине строки или несколько привязок:

<TextBlock>
  <Run Text="Temperature is "/>
  <Run Text="{Binding CelsiusTemp}"/>
  <Run Text="°C"/>  
</TextBlock>

<!-- displays: 0°C (32°F)-->
<TextBlock>
  <Run Text="{Binding CelsiusTemp}"/>
  <Run Text="°C"/>
  <Run Text=" ("/>
  <Run Text="{Binding Fahrenheit}"/>
  <Run Text="°F)"/>
</TextBlock>
денис морозов
источник
6
Мне этот ответ немного больше нравится, потому что я легко могу вставить текст из строковой библиотеки. Конечно, если вы действительно беспокоитесь о интернационализации, вам, вероятно, будет лучше использовать конвертер, чтобы порядок чисел и единиц не был фиксированным. <Run Text = "{x: Static s: UIStrings.General_FahrenheitAbbreviation}" />
Мэтт Беккер
1
Это отличное решение, но я получаю лишние пробелы в окончательном отображении текста между прогонами текста - есть идеи, почему? В вашем примере я вижу0 °C ( 32 °F)
Конрад
Это не очень полезно, если вы хотите выполнить фактическое форматирование строки (например, контролировать количество десятичных знаков и т. Д.).
BrainSlugs83 09
5
@Conrad Если вам не нужны пробелы между запусками, вы должны поместить их в одну строку следующим образом: <TextBlock> <Run Text = "{Binding CelsiusTemp}" /> <Run Text = "° C" / > <Run Text = "(" /: <Run Text = "{Binding Fahrenheit}" /> <Run Text = "° F)" /> </TextBlock>
Ладислав Ондрис
94

Обратите внимание, что использование StringFormat в привязках работает только для "текстовых" свойств. Использование этого для Label.Content не будет работать

Каспер Эренборг
источник
16
Очень важный момент , который взял меня попробовать его , пока я не получил отчаянный и нашел этот комментарий проверить свои подозрения.
DonBoitnott
64
ContentStringFormatприходит на помощь, например: Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
astrowalker 05
2
Спасибо Касперу, настоящему герою, за то, что разместил эту информацию.
DaWiseguy
5
для заголовков GridViewColumn используйтеHeaderStringFormat="{}{0} For Report"
Felix
2
Если вы используете данные времени разработки, вам кажется, что вам нужно перестроить проект после редактирования ContentStringFormat, чтобы изменения отражались в дизайнере, тогда как StringFormat, используемый, скажем, текстовое поле, обновит дизайнер в реальном времени.
Ричард Мур
-8

В xaml

<TextBlock Text="{Binding CelsiusTemp}" />

В ViewModelэтом случае установка значения также работает:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }
Раджеш Натх
источник
19
Это противоречит всей точке зрения разделения View-Viewmodel
Асколеин