在我的wpf应用程序中,我使用Caliburn Micro。现在我创建了一个名为VariableView.xaml的UserControl。Caliburn Micro将查找相应的VariableViewModel.cs。没问题。VariableViewModel类有三个属性,视图使用它们来绑定:VariableName, VariableValue和VariableUnit。例如,温度设置为" temperature ", "40.5"one_answers"°C" .
在我的MainViewModel.cs中,我使用了三次VariableViewModel
public class MainViewModel : PropertyChangedBase
{
public VariableViewModel TempatureViewModel{get;}
public VariableViewModel PressureViewModel{get;}
public VariableViewModel HumidityViewModel{get;}
public MainViewModel()
{
TemperatureViewModel = new VariableViewModel("Temperature", "°C", "40.5");
...
}
}
值显示在视图中。我想做的是从VariableViewModel中派生一个名为TemperatureVariableViewModel的类,它会自动设置VariableName, VariableUnits和VariableValue在构造函数中,如:
public class TemperatureVariableViewModel : VariableViewModel
{
public TemperatureVariableViewModel()
: base("Temperature", "°C", "40.5")
{
}
}
将MainViewModel中的VariableViewModel类型替换为TemperatureViewModel类型会产生问题。现在的问题是视图没有显示。可能Caliburn Micro找不到相应的视图模型了。我该如何解决这个问题?
您可以通过使用ViewLocator.LocateTypeForModelType
的自定义逻辑来实现这一点,这有助于为ViewModels识别视图。例如,您可以从创建属性UseViewOf
开始(下面也将解释不带属性的方法)
[AttributeUsage(AttributeTargets.Class,AllowMultiple =false)]
public class UseViewOfAttribute:Attribute
{
public Type SelectedType { get; set; }
public UseViewOfAttribute(Type type) => SelectedType = type;
}
现在可以用属性
修饰派生类[UseViewOf(typeof(VariableViewModel))]
public class TemperatureVariableViewModel: VariableViewModel
{
现在最后在Bootstrap
类中,您可以使用自己的自定义逻辑覆盖ViewLocator.LocateTypeForModelType
,如下所示
var existingViewLocator = ViewLocator.LocateTypeForModelType;
ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
{
var targetType = existingViewLocator(modelType, displayLocation, context);
if(targetType == null && modelType.GetCustomAttributes<UseViewOfAttribute>().Any())
{
var attribute = modelType.GetCustomAttribute<UseViewOfAttribute>();
targetType = existingViewLocator(attribute.SelectedType,displayLocation,context);
}
return targetType;
};
如果您不想使用attribute,您可以更改自定义逻辑来检索父类的View。例如,
var existingViewLocator = ViewLocator.LocateTypeForModelType;
ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>
{
var targetType = existingViewLocator(modelType, displayLocation, context);
if(targetType == null)
{
while(targetType == null)
{
modelType = modelType.BaseType;
targetType = existingViewLocator(modelType, displayLocation, context);
}
}
return targetType;
};
我更喜欢Attribute方法,因为它使代码更具可读性(未来的开发人员可以很容易地理解哪个视图将用于视图模型)。