c#-Caliburn.Micro框架中的控件命名约定
作者:互联网
Caliburn.Micro允许配置视图和视图模型的命名约定,但是我找不到如何配置控件和方法之间的匹配.我知道我可以只使用Message.Attach附加属性,但是如果可能的话,我想依靠约定.
Caliburn.Micro的约定说,方法的名称必须与控件的名称相同.但是这里存在一个问题:它们的名称经常不同.例如,“保存”和“取消”是方法的好名字,而按钮则是坏名字. SaveButton和CancelButton是按钮的好名字,但是方法的坏名字.考虑到XAML的类型不如C#严格,因此匈牙利表示法也可能有用,但是btnSave和btnCancel之类的名称对于方法而言是不可接受的.
我能找到的最接近的东西是ConventionManager.GetPropertyCaseInsensitive,但是它仅适用于属性,不适用于方法.
问题:如何配置Caliburn.Micro的约定以使其将Save方法附加到SaveButton控件?
解决方法:
这不是我以前尝试过的事情,但是如果您看一下Documentation,则提到了ViewModelBinder类,该类负责将属性,方法等的各种绑定固定到各自的ViewModels.
您的情况特别感兴趣:
ViewModelBinder.BindActions is a Func and thus can be entirely
replaced if desired. Adding to or changing the ElementConventions via
the ConventionManager will also effect how actions are put together.
More on that below.
因此,从本质上讲,应该可以通过定义自己的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标志.
标签:naming-conventions,c,net,mvvm,caliburn-micro 来源: https://codeday.me/bug/20191029/1960817.html