Как привязать несколько значений к одному WPF TextBlock?

210

В настоящее время я использую TextBlockниже, чтобы связать значение свойства с именем Name:

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

Теперь я хочу связать другое свойство IDс тем же именем TextBlock.

Можно ли привязать два или более значений к одному и тому же TextBlock? Можно ли сделать это простым объединением, напримерName + ID и, если нет, как еще это можно сделать?

Проводить
источник

Ответы:

434

Вы можете использовать в MultiBindingсочетании с StringFormatсобственностью. Использование будет выглядеть следующим образом:

<TextBlock>
    <TextBlock.Text>    
        <MultiBinding StringFormat="{}{0} + {1}">
            <Binding Path="Name" />
            <Binding Path="ID" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Задав Nameзначение Fooи IDзначение 1, вы получите вывод в TextBlock Foo + 1.

Note: что это поддерживается только в .NET 3.5 SP1 и 3.0 SP2 или новее.

Ричард МакГвайр
источник
5
@ Привет - я на самом деле не уверен, нужен ли '{}' в этом случае, я включил его, так как он использовался в образце MSDN. В целом, однако, он необходим в качестве escape-последовательности для синтаксического анализатора XAML, чтобы избежать путаницы с расширением разметки Binding.
Ричард МакГуайер
2
У этого есть один побочный эффект. Если вы используете этот метод в чем-то вроде DataGridсортировки, к сожалению, не работает. Более подходящим решением было бы создать свойство «только для чтения» в вашей модели с соответствующим форматом строки для привязки. Излишне говорить, что это удобный способ быстро отформатировать, хотя и немного многословно.
Бретт Райан
34
вам просто нужно {}, когда строка формата начинается с параметра {0}, в этом нет необходимости, если строка формата начинается с текста. пример: "{} {0} + {1}" "Страница {0} из {1}"
Дакиант
Она не работает на WPF проекта .NET 4.0 Visual Studio 2017.
Sorūsh
Решение @ Патрика сработало для меня. Я не мог заставить это работать. У меня была эта ошибкаXamlParseException: A 'Binding' cannot be set on the 'Path' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
Тайсон Уильямс
127

Я знаю, что это слишком поздно, но я решил добавить еще один способ сделать это.

Вы можете воспользоваться тем фактом, что свойство Text можно установить с помощью « Run s», так что вы можете установить несколько привязок, используя Run для каждого из них. Это полезно, если у вас нет доступа к MultiBinding (чего я не нашел при разработке для Windows Phone)

<TextBlock>
  <Run Text="Name = "/>
  <Run Text="{Binding Name}"/>
  <Run Text=", Id ="/>
  <Run Text="{Binding Id}"/>
</TextBlock>
Патрик
источник
4
Это очень удобный подход для использования при привязке к нескольким строкам, которые поставляются как DynamicResource, поскольку для этого нельзя использовать MultiBinding с StringFormat.
Слагстер
Я только что попробовал это. Это работает, однако каждый элемент (даже геометрия), который рисуется (при обновлении), теперь мигает каждый тик по какой-то причине. Собираюсь попробовать другой метод.
Логан Кленнер
6
Это может быть затруднено, если текст должен быть локализован, потому что порядок жестко закодирован.
BlueM
1
Другое использование этого подхода - применение разных стилей для каждой привязки
Хамид Наими
лучший ответ на 2019 год
Фабио до н.э. Соуза
23

Если это просто текстовые блоки (и, следовательно, одностороннее связывание), и вы просто хотите объединить значения, просто свяжите два текстовых блока и поместите их в горизонтальную панель стека.

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}"/>
        <TextBlock Text="{Binding ID}"/>
    </StackPanel>

Это отобразит текст (что и делают все текстовые блоки) без необходимости больше кодировать. Вы могли бы наложить на них небольшое поле, чтобы они выглядели правильно.

CodeWarrior
источник
11

Используйте ValueConverter

[ValueConversion(typeof(string), typeof(String))]
public class MyConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return string.Format("{0}:{1}", (string) value, (string) parameter);
    }

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

        return DependencyProperty.UnsetValue;
    }
}

и в разметке

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

, , ,

<TextBlock Text="{Binding Name, Converter={StaticResource MyConverter Parameter=ID}}" />
Прит Сангха
источник
Да, это было написано 6 лет назад, и вы привязываете «Имя» в качестве первого аргумента к конвертеру (называемое значением в коде) и идентификатор (строку из вопроса) в качестве второго аргумента.
Прит Сангха