Caliburn.Micro框架中的控件命名规范

3
Caliburn.Micro允许配置视图和视图模型的命名约定,但我找不到如何配置控件和方法之间的匹配方式。我知道可以使用"message.attach"附加属性,但如果可能的话,我希望依靠约定。
Caliburn.Micro的约定规定方法的名称必须与控件相同。但是问题在于:它们的名称通常不同。例如,"Save"和"Cancel"是方法的好名称,但不适合用作按钮的名称。"SaveButton"和"CancelButton"是按钮的好名称,但不适合用作方法的名称。考虑到XAML不如C#强类型,匈牙利标记也可能很有用,但像"btnSave"和"btnCancel"这样的名称对于方法来说是不可接受的。
我能找到的最接近的东西是"ConventionManager.GetPropertyCaseInsensitive",但它仅适用于属性,而不适用于方法。
问题:如何配置Caliburn.Micro的约定,使其将"Save"方法附加到"SaveButton"控件上?
1个回答

4
这是我以前没尝试过的事情,但如果您查看文档,就会提到一个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标志。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接