Caliburn.Micro允许为视图和视图模型配置命名约定,但我无法找到如何配置控件和方法之间的匹配。我知道我可以使用Message.Attach
附加财产,但如果可能的话,我想依赖惯例。
Caliburn.Micro的惯例说,方法的名称必须与控件相同。但这里存在一个问题:它们的名称通常不同。例如,Save
和Cancel
是方法的好名称,但是按钮名称不好。 SaveButton
和CancelButton
是按钮的好名称,但是方法名称不好。考虑到XAML的输入类型不如C#,匈牙利表示法也很有用,但btnSave
和btnCancel
这样的名称对方法来说是不可接受的。
我能找到的最接近的是ConventionManager.GetPropertyCaseInsensitive
,但它只适用于属性,而不适用于方法。
问题:如何配置Caliburn.Micro约定以使Save
方法附加到SaveButton
控件?
答案 0 :(得分:4)
这不是我之前尝试过的事情,但是如果你看一下Documentation,就会提到一个ViewModelBinder
课程&#39 ; s负责将各种属性,方法等的绑定修复到各自的ViewModels
。
对您的案件特别感兴趣:
ViewModelBinder.BindActions是一个Func,因此可以完全 如果需要更换。通过添加或更改ElementConventions ConventionManager还将影响操作的组合方式。 更多关于以下内容。
基本上,通过定义自己的BindActions
函数,应该可以获得您之后的行为。
作为一个开始的地方,您可以查看ViewModelBinder.BindActions
的{{3}}并查看当前如何定义该功能。
如果您删除了特定于WinRT的代码,则会留下类似于此内容的内容(您可能不得不删除日志调用):
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
标记。