2017-04-04 1 views
8

Si j'ai une propriété viewmodelEst-il possible de se lier à un champ ValueTuple à WPF avec C# 7

public (string Mdf, string MdfPath) MachineDefinition { get; set; } 

et j'essaie de se lier à en XAML/WPF

<Label Content="{Binding Path=MachineDefinition.Item2}" /> 

ou

<Label Content="{Binding Path=MachineDefinition.MdfPath}" /> 

Je reçois la même erreur

enter image description here

Je vois que les champs ValueTuple sont vraiment champs pas propriétés. Est-ce le problème?

+1

Oui, c'est le problème. –

+0

Vous ne savez pas pourquoi, mais Tuple a des champs de propriété et ValueTuple a des champs de champ. C'est un peu ennuyeux :( – bradgonesurfing

+0

Vous pouvez toujours faire une propriété wrapper comme 'string publique Mdf {get {return MachineDefinition.Mdf;}}'. Ce n'est pas le meilleur (pas même un bon) moyen mais ça devrait marcher :) –

Répondre

6

La confusion est que pour le style ancien Tuple (pre C# 7) tous les éléments étaient propriétés

https://msdn.microsoft.com/en-us/library/dd386940(v=vs.110).aspx

et donc liables. Pour ValueTuple ils sont des champs

https://github.com/dotnet/corefx/blob/master/src/System.ValueTuple/src/System/ValueTuple/ValueTuple.cs#L291

et non liables. Si vous google "WPF Tuple Binding" vous obtenez des charges de faux positifs parce que les tuples de style ancien sont liables mais les nouveaux ne le sont pas.

+1

Il semble que les tuples de valeur violent plusieurs bonnes pratiques: ils exposent des champs publics ET cela signifie qu'ils sont des structures mutables, ce que j'ai toujours pensé être un non-non majeur. Probablement des considérations de performance surpondérer cela. – Evk

0

L'approche MdfPath ne fonctionnera jamais, puisque la partie nom est très restrictive quant à l'endroit où elle existe réellement. Essentiellement, c'est un pur compilateur vaudou, et n'existe pas dans le modèle de type, ce qui signifie que tout ce qui parle au modèle de type (qui inclut la réflexion, les outils UI, les sérialiseurs, etc) seulement les voir les noms , Item2 ; pas les faux noms.

+0

Vous verrez dans ma question que j'ai essayé les deux. Le vrai problème est que ValueTuple utilise des champs alors que Tuple utilise des propriétés. Le premier est unbindable et le dernier liable. – bradgonesurfing

3

Quelque chose que vous pourriez essayer est de mettre en application un convertisseur de valeur. Voici un exemple ...

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}" /> 

Hope this helps.