这不是我以前尝试过的东西,但是如果你看一下Documentation,就会提到一个ViewModelBinder 类,它负责修复属性、方法等的各种绑定。到他们各自的ViewModels。
对您的案例特别感兴趣:
ViewModelBinder.BindActions 是一个 Func,因此可以完全
如果需要更换。通过添加或更改 ElementConventions
ConventionManager 还将影响操作的组合方式。
更多内容如下。
所以本质上,应该可以通过定义自己的BindActions 函数来获得您所追求的行为。
作为一个起点,您可以查看source 的ViewModelBinder.BindActions 并了解该函数当前是如何定义的。
如果您删除 WinRT 特定代码,您会得到如下所示的内容(您可能必须删除 Log 调用):
ViewModelBinder.BindActions =
(namedElements, viewModelType) =>
{
var methods = viewModelType.GetMethods();
var unmatchedElements = namedElements.ToList();
foreach (var method in methods)
{
var foundControl = unmatchedElements.FindName(method.Name);
if (foundControl == null)
{
Log.Info("Action Convention Not Applied: No actionable element for {0}.", method.Name);
continue;
}
unmatchedElements.Remove(foundControl);
var message = method.Name;
var parameters = method.GetParameters();
if (parameters.Length > 0)
{
message += "(";
foreach (var parameter in parameters)
{
var paramName = parameter.Name;
var specialValue = "$" + paramName.ToLower();
if (MessageBinder.SpecialValues.ContainsKey(specialValue))
paramName = specialValue;
message += paramName + ",";
}
message = message.Remove(message.Length - 1, 1);
message += ")";
}
Log.Info("Action Convention Applied: Action {0} on element {1}.", method.Name, message);
Message.SetAttach(foundControl, message);
}
return unmatchedElements;
};
您可以看到Caliburn.Micro 尝试通过将ViewModel 上的可用方法名称与相应View 中存在的控件名称进行比较来将方法绑定到控件。
一种方法可能是简单地添加第二次尝试来查找控件,搜索带有Button 附加的方法名称。这似乎有点违反直觉(从名称中去掉按钮更符合逻辑)。
if (foundControl == null)
{
// Check again for "<Method>Button" named FrameworkElements
foundControl = unmatchedElements.FindName(method.Name + "Button");
if (foundControl == null)
{
Log.Info("Action Convention Not Applied: No actionable element for {0}.", method.Name);
continue;
}
}
显然,这意味着如果您有一个名为SaveButton 的控件和一个名为Save 的控件,则只有最后遇到的一个控件会正确连接。解决方案取决于您是要保留原来的绑定行为,还是只保留这个新行为。
无论哪种情况,整个文档链接都值得一读,因为它提到了其他有趣的东西,例如 ViewModelBinder.ApplyConventionsByDefault 标志。