#c# #wpf #dictionary #binding #tuples
Вопрос:
Если у меня есть свойство viewmodel
public (string Mdf, string MdfPath) MachineDefinition { get; set; }
и я пытаюсь привязаться к нему в XAML / WPF
<Label Content="{Binding Path=MachineDefinition.Item2}" />
или
<Label Content="{Binding Path=MachineDefinition.MdfPath}" />
Я получаю ту же ошибку
Я вижу, что поля ValueTuple на самом деле являются полями, а не свойствами. В этом ли проблема?
Комментарии:
1. Да, в этом-то и проблема.
2. Не знаю почему, но у кортежа есть поля свойств, а у ValueTuple были поля полей. Это немного раздражает 🙁
3. Вы все еще можете сделать свойство оболочки похожим
public string Mdf { get { return MachineDefinition.Mdf; } }
. Это не лучший ( даже не хороший ) способ, но все равно должен сработать 🙂4. Но это не будет поддерживать INPC из коробки. Для этого потребуется больше шаблонов. Моя первоначальная цель состояла в том, чтобы эти два свойства не создавали отдельных событий изменения. Они представляют собой согласованную пару. Мне просто нужно будет создать неизменяемый класс пары на c#. В этом случае значения не работают.
Ответ №1:
Путаница заключается в том, что для кортежа старого стиля ( до C#7 ) все элементы были свойствами
https://msdn.microsoft.com/en-us/library/dd386940(v=против 110).aspx
и, таким образом, можно связать. Для ValueTuple они являются полями
и не поддается привязке.
Если вы прогуглите «Привязка кортежей WPF», вы получите множество ложных срабатываний, потому что старые кортежи в стиле привязываются, но новые-нет.
Комментарии:
1. Похоже, что кортежи значений нарушают несколько хороших практик: они раскрывают общедоступные поля, И это означает, что они являются изменяемыми структурами, что, как я всегда думал, является серьезным недостатком. Вероятно, соображения производительности перевешивают это.
Ответ №2:
Что-то, что вы могли бы попробовать, — это реализовать преобразователь значений. Вот пример…
public class TupleDisplayNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var tuple = value as (Int32 Id, String Name)?;
if (tuple == null)
return null;
return tuple.Value.Name;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
<TextBlock Text="{Binding Converter={StaticResource TupleDisplayNameConverter}, Mode=OneWay}" />
Надеюсь, это поможет.
Ответ №3:
Этот MdfPath
подход никогда не сработает, так как часть имени очень ограничительна с точки зрения того, где она на самом деле существует. По сути, это чистое вуду компилятора и не существует в модели типов, что означает, что все, что обращается к модели типов (включая отражение, инструменты пользовательского интерфейса, сериализаторы и т. Д.), Будет видеть только Item1
Item2
имена, а не поддельные имена.
Комментарии:
1. Вы увидите в моем вопросе, что я пробовал и то, и другое. Реальная проблема заключается в том, что ValueTuple использует поля, в то время как кортеж использует свойства. Первое не поддается привязке, а второе-привязке.