在Caliburn Micro中重用xaml UserControl和视图模型



在我的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方法,因为它使代码更具可读性(未来的开发人员可以很容易地理解哪个视图将用于视图模型)。

相关内容

  • 没有找到相关文章

最新更新