控制Caliburn.Micro框架中的命名约定

时间:2014-05-16 13:17:48

标签: c# .net mvvm naming-conventions caliburn.micro

Caliburn.Micro允许为视图和视图模型配置命名约定,但我无法找到如何配置控件和方法之间的匹配。我知道我可以使用Message.Attach附加财产,但如果可能的话,我想依赖惯例。

Caliburn.Micro的惯例说,方法的名称必须与控件相同。但这里存在一个问题:它们的名称通常不同。例如,SaveCancel是方法的好名称,但是按钮名称不好。 SaveButtonCancelButton是按钮的好名称,但是方法名称不好。考虑到XAML的输入类型不如C#,匈牙利表示法也很有用,但btnSavebtnCancel这样的名称对方法来说是不可接受的。

我能找到的最接近的是ConventionManager.GetPropertyCaseInsensitive,但它只适用于属性,而不适用于方法。

问题:如何配置Caliburn.Micro约定以使Save方法附加到SaveButton控件?

1 个答案:

答案 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标记。