2010-12-10 6 views
6

J'ai des problèmes avec un convertisseur que j'utilise pour convertir entre une chaîne et notre timeformat. Le convertisseur lui-même fonctionne très bien et est implemeneted comme ceci:en utilisant IValueConverter avec DataContext actuel en liaison bidirectionnelle

[ValueConversion(typeof(string), typeof(SimpleTime))] 
    public class StringToSimpleTimeConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      // convert from string to SimpleTime and return it 
     } 
     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      // convert value from SimpleTime to string and return it 
     } 
    } 

Le XAML qui utilise le convertisseur comprend le convertisseur lui-même dans les usercontrol.resources comme ceci:

<converter:StringToSimpleTimeConverter x:Key="stringToSimpleTimeConverter"/> 

Si la propriété est rencontrée (I « utilise la grille de données de la boîte à outils WPF en arrière-plan) le DataTemplate pour l'édition du simpletime est utilisé:

<DataTemplate x:Key="SimpleTimeEditingTemplate"> 
     <TextBox Text="{Binding, Converter={StaticResource stringToSimpleTimeConverter}, Mode=TwoWay}"/> 
</DataTemplate> 

le problème que je rencontre est que le con verter doit avoir un chemin spécifié dans la liaison s'il s'agit d'un convertisseur twoway (et j'en ai besoin dans les deux sens), mais la propriété que je veux définir est déjà le DataContext actuel - Quel chemin puis-je spécifier pour ça?

La seule solution de rechange à laquelle je pourrais penser est d'introduire une propriété factice dans le SimpleTime qui obtient juste le SimpleTime actuel ou le définit.

public class SimpleTime 
{ 
    ... 
    public SimpleTime Clone 
    { 
     get { return new SimpleTime(_amount, _format); } 
     set { this._amount = value._amount; this._format = value._format; } 
    } 
} 

et se lier à celui par

<TextBox Text="{Binding Clone, Converter={StaticResource stringToSimpleTimeConverter}, Mode=TwoWay}"/> 

qui fonctionne très bien, mais est pas vraiment une solution convenable, surtout si j'ai besoin pour convertisseurs plusieurs fois ...

toute aide est apprécié acclamations, manni

Répondre

5

Je pense que vous pouvez contourner comme ça

<TextBox Text="{Binding Path=DataContext, 
         RelativeSource={RelativeSource Self}, 
         Converter={StaticResource stringToSimpleTimeConverter}, 
         Mode=TwoWay}"/> 
+0

J'ai essayé une approche similaire en utilisant un parent usercontrol pour la zone de texte et la liaison à son datacontext. IValueConverter est appelé correctement pour convertir la chaîne en temps simple et revenir pour afficher la chaîne dans le contrôle, mais l'ensemble de la propriété simpletime dans mon infrastructure de données n'est jamais appelé - quelqu'un sait-il comment cela peut se produire? – manni

+0

@manni: J'ai fait un test-application avec ceci et pour moi il semble fonctionner très bien. Il se lie à son propre DataContext, donc je ne vois aucune raison pour qu'il ne fonctionne pas. Êtes-vous sûr que votre méthode ConvertBack n'est jamais appelée? –

+1

merci pour l'effort. Je pense que ce que je veux dire n'était pas assez clair: mes méthodes de conversion et de conversion sont appelées si je change la valeur dans le gui, cela fonctionne bien. mais le paramètre de propriété de la propriété que je définis (la propriété simpletime) n'est pas appelé (le point d'arrêt n'est pas déclenché). Je vais jeter un oeil à cela maintenant, merci beaucoup pour votre aide, j'apprécie vraiment que – manni

0

Au lieu d'introduire une propriété fictive dans votre classe, pourquoi ne pas créer une classe de conteneur comme suit:

public class Container 
{ 
    public Object DataItem { get; set; } 

    //... 
} 

et l'utiliser comme:

<TextBox Text="{Binding DataItem, Converter={StaticResource stringToSimpleTimeConverter}, Mode=TwoWay}"/> 

Ce ne sera pas corrompu/muter votre classe et vous permettent encore existant de faire ce que vous voulez faire.

+0

bonne idée, mais pas vraiment possible pour mes datastructures. Je ne veux pas placer chaque propriété dans un conteneur, et l'objet List parent est directement lié à la grille de données, qui choisit pour chacune des propriétés de la classe une colonne à afficher et éditer, qui aura la propriété directement en tant que datacontext . – manni

+1

Je pense que ce que vous faites est de définir chaque propriété comme un 'DataContext' d'un 'Control' et de les lier en utilisant {{Binding}' sans spécifier de chemin. Si c'est ce que vous faites, c'est faux. Vous devez définir 'DataContext' d'un contrôle parent et tous les contrôles enfants le dérivent. Et utilisez uniquement des liaisons utilisant des chemins différents dans les contrôles enfants. – decyclone

+0

Je pensais que les colonnes de données de données fonctionnaient de cette façon. le datatemplate que j'utilise pour une gridcell dans la grille de données à afficher ou à modifier ne peut pas avoir le datacontext défini sur la structure complète, car cela signifierait qu'il doit maintenant avoir le nom de l'attribut auquel il devrait s'appliquer. ce que je veux, c'est appliquer le datatemplate au type spécifique sans connaître son nom, donc mon codebehind définit la liaison pour la colonne dataagrid et définit ses datatemplates pour les afficher et les modifier. le datatemplate lui-même est appliqué à plus d'un nom de propriété, en fonction des types de propriétés – manni

Questions connexes