2012-08-25 2 views
0

Я написал очень простой ViewModel Locator:Могу ли я получить Смешиваемость назад

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; 
      } 
     } 
    } 
} 

И использовать его так:

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

Он отлично работает во время выполнения, но я потерял расположение времени дизайна. Я подозреваю, что это потому, что я использую относительную привязку, я попытался изменить ее на x:Static, но это не сработает. Есть ли какие-либо предложенные изменения, которые я мог бы сделать, чтобы вернуть мне смешение?

EDIT: О DependencyLocator, это статическая обертка 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)); 
    } 
} 

который получает заполняется в классе app_start в app.xaml. Он был спроектирован таким образом для целей времени разработки, и если я создаю класс локатора с простым представлением, используя объект instanced, определенный в представлении xaml, он действительно получает правильные значения из DependencyLocator, только после того, как я переключился на Свойства зависимостей, эта проблема подошел.

+0

Что вы имеете в DependencyLocator.GetInstance? вы используете там инфраструктуру DI/IoC? ... если да, то какой? –

+0

@colinsmith Я добавил для вас редактирование. – deanvmc

+0

Предполагаю, что ваш Ninject bootstrapper/Kernel не будет вызван в DesignTimes, поэтому нет никаких типов, которые могут быть введены. Вы называли свой BootStrapper/ядро ​​во время выполнения? –

ответ

0

Этот код просто уточняя, что вы пытаетесь достичь:

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

Я вижу, что вы пытаетесь сделать с этим, но это не сработало. – deanvmc

+0

Взгляните на мои изменения .... скажите, если я интерпретирую то, что вы пытаетесь сделать неправильно .... также делает OnLocateForChanged определенно называемым runtime, и вы проследили его? ... .check object/type, для которого задана переменная «var view». –

+0

Нет, вы правы в своих изменениях, я захватываю представление, потом его имя, затем заменяю View на ViewModel и получаю его из контейнера IoC. Да OnLocateForChanged попадает во время выполнения (отладка подтверждена). – deanvmc