2012-08-25 2 views
0

j'ai écrit un ViewModel très simple Locator:Puis-je obtenir mon blendability retour

public static readonly DependencyProperty LocateForProperty = 
    DependencyProperty.RegisterAttached("LocateFor", 
    typeof (Object), 
    typeof (ViewModelLocator), 
    new PropertyMetadata(null, OnLocateForChanged)); 

public static object GetLocateFor(DependencyObject dependencyObject) 
{ 
    return dependencyObject.GetValue(LocateForProperty); 
} 

public static void SetLocateFor(DependencyObject dependencyObject, Object value) 
{ 
    dependencyObject.SetValue(LocateForProperty, value); 
} 

private static void OnLocateForChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs) 
{ 
    if (dependencyObject != null) 
    { 
     var viewModelName = dependencyObject.GetType().AssemblyQualifiedName; 
     if (! string.IsNullOrEmpty(viewModelName)) 
     { 
      viewModelName = viewModelName.Replace("View", "ViewModel"); 
      var viewModel = DependencyLocator.GetInstance(Type.GetType(viewModelName)); 
      if (viewModel != null) 
      { 
       ((FrameworkElement) dependencyObject).DataContext = viewModel; 
      } 
     } 
    } 
} 

et de l'utiliser comme ceci:

<vm:ViewModelLocator.LocateFor> 
    <Binding RelativeSource="{RelativeSource Self}" /> 
</vm:ViewModelLocator.LocateFor> 

Il fonctionne parfaitement à l'exécution, mais j'ai perdu l'emplacement de la conception. Je suppose que c'est parce que j'utilise la liaison relative, j'ai essayé de le changer à x:Static mais cela ne fonctionne pas. Y a-t-il des changements suggérés que je pourrais faire qui me redonneraient Blendability?

EDIT: A propos DependencyLocator, il est une enveloppe statique autour Ninject:

using System; 
using System.Collections.Generic; 

/// <summary> 
/// Defines an object that wraps around specific DI containers. 
/// </summary> 
public static class DependencyLocator 
{ 
    /// <summary> 
    /// Gets or Sets the function used for locating a single instance of a specifc type. 
    /// </summary> 
    public static Func<Type, object> GetInstance; 

    /// <summary> 
    /// Gets or Sets the function used for locating all instance of a specific type. 
    /// </summary> 
    public static Func<Type, IEnumerable<object>> GetAllInstances; 

    /// <summary> 
    /// Gets the implementation of the provided service. 
    /// </summary> 
    public static T Get<T>() 
    { 
     return (T)GetInstance(typeof(T)); 
    } 

    /// <summary> 
    /// Gets all implementations of the provided service. 
    /// </summary> 
    public static IEnumerable<T> GetAll<T>() 
    { 
     return (IEnumerable<T>) GetAllInstances(typeof (T)); 
    } 
} 

qui obtient peuplé dans une classe app_start dans app.xaml. Il a été conçu de cette manière pour la conception et si je crée une classe de localisateur de modèle simple utilisant un objet instancié défini dans le xaml de la vue, il obtient les valeurs correctes de DependencyLocator, c'est seulement depuis que je suis passé aux propriétés de dépendance. est venu.

+0

Qu'est-ce que vous avez à DependencyLocator.GetInstance? utilisez-vous un framework DI/IoC là-dedans? ... si oui, lequel? –

+0

@colinsmith J'ai ajouté une modification pour vous. – deanvmc

+0

En supposant que j'imagine que votre Bootstrapper/Kernel Ninject ne soit pas appelé à DesignTimes, il n'y a pas de type de configuration qu'il peut injecter. Appelez-vous votre BootStrapper/kernel à l'exécution? –

Répondre

0

Ce code est juste clarifier ce que vous essayez d'atteindre:

// Use this to trigger break into debugger when debugging another instance of Visual Studio in order to debug the behaviour at design time. 
System.Diagnostics.Debugger.Break(); 

if (dependencyObject != null) 
{ 
    var view = GetLocateFor(dependencyObject); // or instead of this access the changed value through the eventargs 

    var viewModelName = view.GetType().AssemblyQualifiedName; 

    if (! string.IsNullOrEmpty(viewModelName)) 
    { 
     viewModelName = viewModelName.Replace("View", "ViewModel"); 
     var viewModel = DependencyLocator.GetInstance(Type.GetType(viewModelName)); 
     if (viewModel != null) 
     { 
      ((FrameworkElement) view).DataContext = viewModel; 
     } 
    } 
} 
+0

Je vois ce que vous essayez de faire avec ceci mais cela n'a pas fonctionné. – deanvmc

+0

Jetez un oeil à mes changements .... dites-moi si je suis en train d'interpréter ce que vous essayez de faire à tort .... est-ce que le OnLocateForChanged est définitivement appelé runtime, et vous l'avez tracé? ... .check l'objet/type auquel la variable "var view" est définie. –

+0

Non, vous avez raison dans vos modifications, je saisis la vue, puis son nom, puis le remplacement de View avec ViewModel et l'obtention du conteneur IoC. Oui, le OnLocateForChanged est atteint lors de l'exécution (débogage confirmé). – deanvmc