这是我以前没尝试过的事情,但如果您查看
文档,就会提到一个
ViewModelBinder
类,负责修复各种绑定的属性、方法等到相应的
ViewModels
。在你的情况下,特别感兴趣的是:
ViewModelBinder.BindActions是一个Func,因此如果需要,可以完全替换它。通过ConventionManager添加或更改ElementConventions也会影响如何组合操作。下面将详细介绍。
因此,本质上,通过定义自己的
BindActions
函数,应该可以获得您想要的行为。
作为起点,您可以查看
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
标志。