mvvmcross - 绑定(bind)到操作方法

标签 mvvmcross

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

示例:

    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" />

它不能开箱即用,我测试过。

虽然我找到了很多关于添加新目标绑定(bind)的示例,但我没有找到任何关于添加新绑定(bind)的示例。

更新:
现在,它可以与 Rio 绑定(bind)一起开箱即用。要使用它,请将 MvvmCross MethodBinding NuGet 包添加到 Android 项目中。

最佳答案

到目前为止,MvvmCross 的重点一直是允许多平台目标绑定(bind),而源代码仍然主要是“普通”INotifyPropertyChanged

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

最近,该区域还记录了几个新功能请求:

因此,我确实希望将来在该领域会公开更多功能......


话虽如此,如果您今天想让它正常工作,那么 MvvmCross Binding 是可重写的,因此您可以相当轻松地做到这一点:

1. 实现一个使用反射调用 MethodInfo 的 ICommand(为了完整起见,这可能还应该使用一个参数(如果可用)) - 某种 InvokeMethodCommand (此代码留给读者!)

.

2. 实现一个包装 InvokeMethodCommandMyMethodSourceBinding 类 - 类似于:
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;
    }
}
3. 使用您自己的实现覆盖 MvvmCross 注册的 IMvxSourceBindingFactory ,该实现可以检测方法何时存在 - 遗憾的是,今天大部分都是剪切和粘贴代码 - 它将类似于
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);
    }
}
4. 在您​​自己的自定义绑定(bind)构建器中提供此源绑定(bind)工厂 - 例如:
public class MyAndroidBindingBuilder
    : MvxAndroidBindingBuilder
{
    protected override IMvxSourceBindingFactory CreateSourceBindingFactory()
    {
        return new MvxSourceBindingFactory();
    }
}
5. 在设置期间提供此绑定(bind)构建器
public class Setup : MvxAndroidSetup
{
    // ....

    protected override MvxAndroidBindingBuilder CreateBindingBuilder()
    {
        return new MyAndroidBindingBuilder();
    }
}

注意:这种方法目前仅适用于高级用户...正如本问题第一部分中所建议的那样,我确实预计该区域的代码会发生很大变化,因此您可能还会遇到维护 fork 的一些问题在这个区域。 (事实上​​,在 GitHub 存储库的西藏绑定(bind)分支上,这方面的代码已经发生了相当大的变化!)

关于mvvmcross - 绑定(bind)到操作方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17351375/

相关文章:

windows - MvvmCross Windows Phone 8.1 绑定(bind)列表选择到命令,编译失败

xamarin.android - 升级到 6.0 版本后 MvvmCross App 无法启动

xamarin.android - ItemClick 用于 MvxLinearLayout? MVVMCross 5

android - 通过数据链接打开 MvvmCross 应用程序

android - MvvmCross:MvxAdapter GetBindableView 方法在第一个 child 上无限循环

ios - 从多个 View 模型创建 View

c# - 如何使用 Android Xamarin 和 MvvmCross MvxTabsFragmentActivity 创建选项卡

xamarin.ios - MonoTouch 和 MonoDroid 中的崩溃报告

android - 从堆栈中弹出多个 fragment

wpf - 在 WPF 中使用 MvxVisibilityValueConverter