绑定行动方法

时间:2013-06-27 19:12:34

标签: mvvmcross

是否可以使用简单的操作方法 - 就像使用Caliburn.Micro一样 - 而不是使用MvvmCross绑定的命令?

示例:

    public void Action()
    {
        Tip = 11;
    }

<Button
    android:text="Button"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/button1"
    local:MvxBind="Click Action" />

开箱即用,我测试了它。

虽然我发现了很多关于添加新的目标绑定的示例,但我没有找到关于添加新绑定的单一内容。

更新
这与Rio绑定开箱即用。要使用它,请将MvvmCross MethodBinding NuGet包添加到 Android 项目。

1 个答案:

答案 0 :(得分:3)

到目前为止,MvvmCross的重点一直是允许多平台目标绑定,其中源仍然主要是“香草”INotifyPropertyChanged

ViewModel结构存在一些偏差 - 例如:

最近,该领域也记录了几个新的功能请求:

由于这些原因,我希望将来可以在这个领域展示更多功能......


话虽如此,如果你想让它今天正常工作,那么MvvmCross Binding是可以覆盖的,所以你可以很容易地做到这一点:

1.实现使用反射调用MethodInfo的ICommand(为了完整性,这应该也可以使用参数) - 某种InvokeMethodCommand(此代码留给读者!)

2.实现一个包含MyMethodSourceBinding的{​​{1}}类 - 类似于:
InvokeMethodCommand
3.使用您自己的实现覆盖MvvmCross注册的public class MyMethodSourceBinding : MvxSourceBinding { private readonly MethodInfo _methodInfo; protected MyMethodSourceBinding(object source, MethodInfo methodInfo) : base(source) { _methodInfo = _methodInfo; } public override void SetValue(object value) { // do nothing - not allowed } public override Type SourceType { get { return typeof(ICommand); } } public override bool TryGetValue(out object value) { value = new InvokeMethodCommand(source, _methodInfo); return true; } } ,该实现可以检测何时存在方法 - 遗憾的是,大多数情况下今天都是剪切和粘贴编码 - 它会像
IMvxSourceBindingFactory
4.在您自己的自定义绑定构建器中提供此源绑定工厂 - 例如:
public class MySourceBindingFactory
    : IMvxSourceBindingFactory
{
    private IMvxSourcePropertyPathParser _propertyPathParser;

    private IMvxSourcePropertyPathParser SourcePropertyPathParser
    {
        get
        {
            if (_propertyPathParser == null)
            {
                _propertyPathParser = Mvx.Resolve<IMvxSourcePropertyPathParser>();
            }
            return _propertyPathParser;
        }
    }

    public IMvxSourceBinding CreateBinding(object source, string combinedPropertyName)
    {
        var tokens = SourcePropertyPathParser.Parse(combinedPropertyName);
        return CreateBinding(source, tokens);
    }

    public IMvxSourceBinding CreateBinding(object source, IList<MvxPropertyToken> tokens)
    {
        if (tokens == null || tokens.Count == 0)
        {
            throw new MvxException("empty token list passed to CreateBinding");
        }

        var currentToken = tokens[0];
        if (tokens.Count == 1)
        {
            return CreateLeafBinding(source, currentToken);
        }
        else
        {
            var remainingTokens = tokens.Skip(1).ToList();
            return CreateChainedBinding(source, currentToken, remainingTokens);
        }
    }

    private static MvxChainedSourceBinding CreateChainedBinding(object source, MvxPropertyToken propertyToken,
                                                                    List<MvxPropertyToken> remainingTokens)
    {
        if (propertyToken is MvxIndexerPropertyToken)
        {
            return new MvxIndexerChainedSourceBinding(source, (MvxIndexerPropertyToken) propertyToken,
                                                          remainingTokens);
        }
        else if (propertyToken is MvxPropertyNamePropertyToken)
        {
            return new MvxSimpleChainedSourceBinding(source, (MvxPropertyNamePropertyToken) propertyToken,
                                                         remainingTokens);
        }

        throw new MvxException("Unexpected property chaining - seen token type {0}",
                               propertyToken.GetType().FullName);
    }

    private static IMvxSourceBinding CreateLeafBinding(object source, MvxPropertyToken propertyToken)
    {
        if (propertyToken is MvxIndexerPropertyToken)
        {
            return new MvxIndexerLeafPropertyInfoSourceBinding(source, (MvxIndexerPropertyToken) propertyToken);
        }
        else if (propertyToken is MvxPropertyNamePropertyToken)
        {
            //**************************
            // Special code is here

            var propertyToken = (MvxPropertyNamePropertyToken) propertyToken;

            if (source != null)
            {
                var method = source.GetType().GetMethod(propertyToken.PropertyName, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
                if (method != null)
                {
                     return new MyMethodSourceBinding(source, method);
                }
            }  
            return new MvxSimpleLeafPropertyInfoSourceBinding(source,
                                                                  (MvxPropertyNamePropertyToken) propertyToken);

            // Special code ends here
            //**************************
        }
        else if (propertyToken is MvxEmptyPropertyToken)
        {
            return new MvxDirectToSourceBinding(source);
        }

        throw new MvxException("Unexpected property source - seen token type {0}", propertyToken.GetType().FullName);
    }
}
5.在安装过程中提供此绑定构建器
public class MyAndroidBindingBuilder
    : MvxAndroidBindingBuilder
{
    protected override IMvxSourceBindingFactory CreateSourceBindingFactory()
    {
        return new MvxSourceBindingFactory();
    }
}

注意:此方法仅适用于高级用户...正如本问题的第一部分所述,我确实希望此区域中的代码发生很大变化,因此您可能还会遇到一些维护分叉的问题在这方面。 (事实上​​,GitHub回购中的西藏绑定分支在这方面的代码已经发生了很大变化!)