2009-06-03 5 views
4

J'utilise modèle MV-VMvaleur Obtenir de DataContext à MarkupExtension

Dans mon VM je code comme

public class ViewModel { 
    public XmlDocument Document { ... } 
    .... 
} 

J'ai une extension de balisage à partir de laquelle je voudrais utiliser ce document

public override object ProvideValue(IServiceProvider serviceProvider) { 
     IProvideValueTarget valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
     if (valueProvider != null) { 
      DependencyObject target = valueProvider.TargetObject as DependencyObject; 
      XmlDocument doc = Foo.GetDocument(target); 
      if (doc != null) { 
       var n = doc.SelectSingleNode("/.../text()"); 
       if (n != null) return n.Value; 
      } 
     } 
     return "«" + ObjectProperty + "»"; 
    } 

J'ai créé Foo.Document de propriété attachée, et attaché à ma page (DataContext de la page est définie à une instance de ma classe ViewModel

<Page ... lc:Foo.Document="{Binding Document}"> 
    ... 
</Page> 

(afin de ne pas avoir à taper comme un paramètre chaque fois que j'utilise l'extension de balisage)

Maintenant, dans mon extension de balisage lorsque je tente de lire la propriété de document ci-joint, je reçois toujours un document nul. En débuggant la liaison, elle voit comme un problème de synchronisation dans cette propriété attachée obtient une valeur correcte après l'exécution de l'extension de balisage.

Est-il possible de faire en sorte que cela fonctionne?

Répondre

1

Vous pourriez câbler un événement à l'événement Loaded ou Initialized sur la page à partir de vos extensions de balisage, peut-être. Ou peut-être que vous pourriez mettre votre extension de balisage dans le fichier XAML après le Foo.Document est mentionné.

Merci, Rob Relyea équipe WPF/XAML my blog

6

La méthode ProvideValue est appelée deux fois, lorsque le XAML est évalué par l'analyseur et une fois que lorsque les valeurs sont chargées. Lors de ce premier appel, le targetObject est simplement une sorte d'objet factice appelé SharedDP et non l'objet auquel l'extension markup est appliquée. Vous devez ignorer ce premier appel et traiter uniquement le second appel. Ceci est le code fonctionne dans notre application.

public override object ProvideValue(IServiceProvider serviceProvider){         
       var pvt = serviceProvider as IProvideValueTarget; 
       if (pvt == null) 
       { 
        return null; 
       } 


       var frameworkElement = pvt.TargetObject as FrameworkElement; 
       if (frameworkElement == null) 
       { 
        return this; 
       } 
//.... Code will run once the markup is correctly loaded 
var dataContext = frameworkElement.DataContext; 


    } 
+2

Cela ne se produit pas du tout pour moi ... nous appelle une seule fois – flq

+0

Grand travail; Cela a résolu mon problème. Notez que certains de ces appels "fictifs" préparatoires sont votre seule opportunité d'obtenir - et d'enregistrer pour plus tard - d'autres types de contextes de fournisseurs de services dont vous pourriez avoir besoin. Je me réfère en particulier à l'élément WPF NameScope et/ou racine approprié (WPF utilise son propre mécanisme de noms au lieu de XAML pour FrameworkElements, etc.), ce qui est presque impossible à obtenir sur certains des derniers appels ProvideValue lorsque vous êtes dedans un modèle de contrôle. –

Questions connexes