尝试将我的第一个MarkupExtension作为服务定位器,并使用它来获取我的XAML中的DataContext:
ViewModel和接口
public interface IMainViewModel
{
ICommand OpenProjectCommand { get; }
}
public class MainViewModel : IMainViewModel
{
public ICommand OpenProjectCommand { get; private set; }
...
}
服务定位器:
public static class ServiceLocator
{
public static void Map<T>(object concreteType)
{
// store type
}
public static T GetInstance<T>() where T : class
{
// get, instantiate and return
}
}
App.xaml
protected override void OnStartup(StartupEventArgs e)
{
ServiceLocator.Map<IMainViewModel>(typeof(MainViewModel));
base.OnStartup(e);
}
MarkupExtension:
public class ServiceLocatorExtension : MarkupExtension
{
public Type ServiceType { get; set; }
public ServiceLocatorExtension(Type type)
{
ServiceType = type;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (ServiceType == null)
throw new ArgumentException("Type argument is not specified");
var instance = ServiceLocator.GetInstance<IMainViewModel>(); // how to use this.ServiceType?
return instance;
}
}
XAML:
<Window ... DataContext="{loc:ServiceLocator {x:Type loc:IMainViewModel}}">
...
<Button ... Command="{Binding OpenProjectCommand}"/> // problem complains cannot resolve in datacontext type of "object"
问题:
1)如何在MarkupExtension中使用this.ServiceType属性,而不是显式接口?
2) XAML中按钮上的命令绑定报告它不能从object类型的datacontext中解析,所以我得到了一个警告,这是我不想要的。如何让它知道它的正确类型?
发布于 2015-11-16 09:19:00
不确定这是否是最好的解决方案,仍在寻找替代方案。
1:
使用反射:
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (ServiceType == null)
throw new ArgumentException("Type argument is not specified");
var serviceLocatorMethod = typeof(ServiceLocator).GetMethod("GetInstance").MakeGenericMethod(ServiceType);
return serviceLocatorMethod.Invoke(null, null);
}
2:
由于这是一个设计者的问题,这解决了这个问题:
d:DataContext="{d:DesignInstance loc:MainViewModel}"
https://stackoverflow.com/questions/33724162
复制