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が、うまくいきません。Blendability を取り戻すための変更の提案はありますか?

編集: 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.xaml の app_start クラスに取り込まれます。設計時の目的でこのように設計されており、ビューの xaml で定義されたインスタンス化されたオブジェクトを使用して単純なビュー モデル ロケーター クラスを作成すると、実際に DependencyLocator から正しい値が取得されます。出てきました。

4

1 に答える 1

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;
        }
    }
}
于 2012-08-25T19:50:27.157 に答える