我写了一个非常简单的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类中填充。它是出于设计时的目的设计的,如果我使用View的xaml中定义的实例对象创建一个简单的视图模型定位器类,它确实从DependencyLocator获取了正确的值,它只是因为我切换到Dependency Properties这个问题来了。
答案 0 :(得分: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;
}
}
}