Что такое привязка данных WPF XAML, эквивалент String.Format?

Или, чтобы быть более ясным, как я могу отформатировать блок текста (в моем случае, чтобы он был включен во всплывающую подсказку) так, чтобы некоторые части текста происходили из связанных значений.

На простом C # я бы использовал:

_toolTip.Text = string.Format("{1:#0}% up, {2:#0}% down",
    Environment.NewLine, percentageOne, percentage2);

Однако разметка WPF XAML для свойства Text может содержать только одну привязку. Фигурные скобки вселяли в меня большие надежды, но это невозможно:

<Element>
  <Element.Tooltip>
    <!-- This won't compile -->
    <TextBlock Text="{Binding Path=PercentageOne}% up, {Binding Path=PercentageTwo}% down"/>
  </Element.Tooltip>
</Element>

Я читал, что свойство Run.Text не является свойством зависимости и поэтому не может быть привязано.

Есть ли способ выполнить это форматирование в XAML?


person Drew Noakes    schedule 15.01.2009    source источник


Ответы (5)


Вы можете использовать MultiBinding + StringFormat (требуется WPF 3.5 SP1):

<TextBox.Text>
    <MultiBinding StringFormat="{}{1:#0}% up, {2:#0}% down">
      <Binding Path="PercentageOne" />
      <Binding Path="PercentageTwo"/>
    </MultiBinding>
</TextBox.Text>

Что касается Run.Text - вы не можете привязаться к нему, но есть несколько обходных путей:

person aku    schedule 15.01.2009
comment
круто, не знал об этой новой функции. Вы знаете, что представляют собой пустые волнистые линии в начале строки? - person Michael Meadows; 15.01.2009
comment
{} необходимо указать WPF не рассматривать {something} как расширение разметки. - person aku; 15.01.2009
comment
Ура, аку. К сожалению, я не нацелен на SP1, так что придется убирать его. Тем не менее, я думаю, что это самый элегантный ответ, поэтому я дал его вам. - person Drew Noakes; 15.01.2009
comment
Спасибо за ссылку на BindableRun! - person John Fisher; 12.07.2009

Я бы разделил на несколько текстовых блоков, привязывая каждый к StringFormat = {0: P} в привязке как таковой:

<TextBox Text="{Binding Something, StringFormat=\{0:P\}}" />

Примеры см. В этом сообщении: Блог Лестера WPF о StringFormat

Checkout VS2010 - привязка из свойств включает форматирование в параметрах.

person Dave    schedule 09.02.2010

Если вы используете 3.5 SP1, ответ от Аку - это то, что вам нужно. В противном случае вы можете использовать FormatConverter из моей библиотеки WPF Converters.

person Kent Boogaart    schedule 15.01.2009
comment
Спасибо, Кент, они выглядят полезными, я проверю их сегодня. Кстати, форматирование на указанной вами странице codeplex не совсем правильное в конце примеров кода (по крайней мере, в Chrome на WinXP). - person Drew Noakes; 16.01.2009

Раньше я решал эту проблему, фактически разбивая TextBlock, который есть в вашем листинге, на несколько TextBlocks. Попробуйте что-то вроде этого:

<Element>
  <Element.Tooltip>
    <StackPanel Orientation="Horizontal">
      <TextBlock Text="{Binding Path=PercentageOne}"/>
      <TextBlock Text="% up, "/>
      <TextBlock Text="{Binding Path=PercentageTwo}"/>
      <TextBlock Text="% down"/>
    </StackPanel>
  </Element.Tooltip>
</Element>

В качестве альтернативы вы можете создать что-то вроде StringFormatConverter, который мог бы принимать строку формата в качестве параметра и использовать MultiBinding для передачи ему параметров. См. Эту ссылку для MultiBindings:

MultiBinding Info

И этот для информации о конвертерах:

Информация о преобразователях

Вы можете довольно легко представить преобразователь, который принимает «значения объекта []» вместо «значения объекта» в качестве первого параметра и передает их в функцию форматирования.

person Gabe    schedule 15.01.2009
comment
увеличение количества визуальных элементов может снизить производительность, также эта разметка может работать по-другому, когда происходит переполнение текста - person aku; 15.01.2009
comment
Спасибо за ответ. Я рассматривал подход StackPanel, но он кажется немного неуклюжим, и я надеялся на что-то лучшее. Кроме того, как говорит Аку, он не мог аккуратно завернуться. К сожалению, я не использую SP1, поэтому не могу использовать MultiBinding. - person Drew Noakes; 15.01.2009
comment
WrapPanel решит проблему упаковки вместо StackPanel. - person Jon Comtois; 24.04.2010

Насколько мне известно, WPF не делает то, что вам нужно. У вас есть гораздо более мощное (хотя и более сложное) решение.

Взгляните на интерфейс IValueConverter.

Ссылка на MSDN HowTo здесь

ИЗМЕНИТЬ

Основываясь на ответе aku и вашем утверждении, что вы не можете использовать 3.5 SP1, вот альтернатива.

Взгляните на недавнюю серию публикаций Фила Хаака о форматировании строк:

Создайте ValueConverter, поскольку он принимает формат как свойство. Затем вы должны иметь возможность привязать свой объект данных и иметь его формат на основе вашего определенного формата (используя имя свойства вместо позиции).

person Michael Meadows    schedule 15.01.2009
comment
Привет Майкл. Спасибо, но я надеялся сделать что-то более декларативное в XAML, вместо того, чтобы писать тип .NET, специально удовлетворяющий моим требованиям. Его нельзя будет повторно использовать вне этого контекста, как можно использовать String.Format. - person Drew Noakes; 15.01.2009