6
votes

La liaison de données à double sens avec le convertisseur ne met pas à jour la source

J'ai une liaison de données configurée avec un convertisseur pour transformer une source XML maladroite en un arbre de classes internes d'affichage et d'édition. Tout fonctionne bien pour la lecture de la source XML, mais je vais avoir un diable de temps à essayer d'obtenir des modifications apportées aux classes internes pour se propager à la source XML.

Voici le XAML pour le site d'utilisation: P>

public static readonly DependencyProperty SampleProperty =
    DependencyProperty.Register("Sample", typeof(SampleType), typeof(SampleControl), new PropertyMetadata(new PropertyChangedCallback(OnSampleChanged)));

public SampleType Sample
{
    get { return (SampleType)GetValue(SampleProperty); }
    set { SetValue(SampleProperty, value); }
}

private static void OnSampleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue != null)
    {
        ((INotifyPropertyChanged)e.NewValue).PropertyChanged += ((SampleControl)d).MyPropertyChanged;
    }
    else if (e.OldValue != null)
    {
        ((INotifyPropertyChanged)e.OldValue).PropertyChanged -= ((SampleControl)d).MyPropertyChanged;
    }
}

private void MyPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    ;  // breakpoint here shows change notices are happening
}


7 commentaires

Votre exemple de code pour changement de propriété indique que les propriétés de l'échantillon changent, pas l'échantillon lui-même.


@RagePoTatoTatoTato: Préférez-vous que la liaison de données ne fonctionne que si une nouvelle instance est attribuée à la propriété exemple, mais pas si les propriétés de l'instance existante mentionnée par l'exemple de propriété sont modifiées et signalent leurs modifications via InotifyProperTychanged?


Oui. L'échantillon n'a jamais changé. C'est le même objet. Propriétés à l'intérieur qu'elle a changé. Vous pouvez tester cela. Mettez un bouton sur votre contrôle une fois que tout est chargé et que l'échantillon obtient son attribution initiale de votre VM. Attribuez ensuite un échantillon à un nouveau sampleType. N'oubliez pas qu'il doit être le type approprié ou le moteur de liaison l'ignorera. Si vous configurez votre reliure à deux reprises, vous verrez votre conversion de retour appelé.


En outre, quelque chose que j'ai trouvé de valeur une fois la découverte, si vous souhaitez une liaison à deux voies par défaut sur votre DP, vous pouvez utiliser FramewordProperTymetadata au lieu de Propertymetadata et définir Bindstwowayybydefault. Juste pour te dire un peu xaml :)


Cela donne un sens pour les types de valeur où le contenu est atomique mais pas pour les types de référence plus couramment visualisés (conceptuellement) comme la somme de leurs propriétés. En particulier, lorsqu'un convertisseur est impliqué - si les propriétés de la valeur converties changent, l'état de la valeur convertie a changé et que cela doit être communiqué à la propriété source via ConvertBack. Sinon, les convertisseurs ne sont utiles que pour les types de valeur et les objets immuables.


Ne pas discuter de votre point, ventilez simplement des frustrations WPF en général. : P


Je sais exactement ce que tu veux dire et je suis couru dans cette même chose auparavant. Vous pouvez gérer la propriété de modifier la notification sur la machine virtuelle à la place. J'espère que tout cela a aidé.


3 Réponses :


0
votes

xmlsource est une propriété de lecture-écriture CLR (non dépendanceProperty) du parent Objet lié des données. C'est un type .NET généré à partir d'un XSD.

Je crois que c'est votre problème. Une propriété CLR de base n'offrira pas et n'est donc pas incapable de participer à la base de données bidirectionnelle. Je suppose que vous obtiendrez une liaison unique? Avez-vous des erreurs de diffusion de base de données dans votre fenêtre de sortie?

Vous pouvez essayer de créer une enveloppe contenant la classe de la propriété XMLSource, rendez-vous de cette classe mise en œuvre inotifypropertychanged et exposer xmlsource comme une propriété notifiante (elle est pas doit être une propriété de dépendance).

Aussi, concernant ce commentaire:

Vous dites que les données neigant que fonctionne si une nouvelle instance est attribuée à l'exemple de propriété, mais pas si Propriétés de l'instance existante mentionné par l'exemple de propriété sont changé et signalez leurs modifications via Inotifypropertychangned?

Les exemples de mises en oeuvre d'inotifyPropertychanged ont généralement la notification de la notification lorsque la propriété elle-même change, non pas lorsque des enfants ou d'autres propriétés changent. Cependant, vous pouvez absolument licencier l'événement de notification sur une propriété à tout moment. Par exemple, vous pouvez avoir un «nom complet» qui notifie chaque fois que «prénom» ou «nom de famille».

Si ce qui précède n'est pas utile, je suggérerais de poster un peu plus de votre Code - peut-être une reprophérose simplifiée de ce que vous essayez de travailler.

Edit:

Je pense que j'ai mal compris votre question. Je pense que le problème est ce que vous avez fait allusion dans vos commentaires - c'est un type de référence. Peut-être la peine d'essayer cela dans votre oimaplecharged: xxx

Je pense que cela obligera le système de liaison à reconnaître que quelque chose a changé sur le côté cible.


1 commentaires

La propriété CLR XMLSource implémente déjà inotifyPropertychanged. En outre, le convertisseur de convertisseur devrait être appelé en premier afin d'obtenir une valeur à attribuer à la propriété XMLSource et de convertir n'est pas appelée.



2
votes

avec des allusions de plusieurs questions similaires et presque des réponses ici. J'ai donc une solution de travail qui conserve la liaison. Vous pouvez forcer manuellement la liaison à mettre à jour la source dans un événement stratégiquement placé, tel que LostFocus: xxx


0 commentaires

0
votes

eu un problème similaire. La solution était la suivante:

au lieu de la liaison à deux voies, j'ai utilisé un moyen et un convertisseur. Le convertisseur convertit (encapsulate) l'objet (dans votre cas, l'objet parent de la propriété XMLSource) à une vue de vue, et le contrôle se lie à celui-ci.

Le point de vue fonctionne comme un proxy, contient une référence à l'objet, gère ses propriétés, et bien sûr des outils inotifypropertychanged. Dans ce cas, vous n'avez pas besoin d'appeler la méthode de reconverte, car les opérations sont effectuées sur l'instance appropriée via la viewModel.

Vous avez donc une vue imprenable, vous n'avez pas besoin de code dans le fichier xaml.cs


0 commentaires