Xamarin Forms - 获取绑定表达式

4
在Silverlight (以及其他基于XAML的技术)中,有一个名为 GetBindingExpression 的方法,它允许我们检查给定依赖属性上的绑定。该方法在 FrameworkElement 上,因此每个控件都可以让我们访问绑定表达式。
例如:
var selectedItemBindingExpression = GetBindingExpression(SelectedItemProperty);

但是,在Xamarin Forms中似乎没有相应的等价物。有没有一种方法可以从Xamarin Forms中的BindableProperty属性中获取绑定表达式?

2个回答

13

我不相信在Xamarin.Forms中有任何公共API可用于访问BindingExpression,但您可以使用反射来访问相关的Binding,从而访问BindingExpression

public static class BindingObjectExtensions
{
    public static Binding GetBinding(this BindableObject self, BindableProperty property)
    {
        var methodInfo = typeof(BindableObject).GetTypeInfo().GetDeclaredMethod("GetContext");
        var context = methodInfo?.Invoke(self, new[] { property });

        var propertyInfo = context?.GetType().GetTypeInfo().GetDeclaredField("Binding");
        return propertyInfo?.GetValue(context) as Binding;
    }

    public static object GetBindingExpression(this Binding self)
    {
        var fieldInfo = self?.GetType().GetTypeInfo().GetDeclaredField("_expression");
        return fieldInfo?.GetValue(self);
    }
}

示例用法 - 获取绑定表达式

var expr = this.GetBinding(TextProperty).GetBindingExpression();

样例用法 - 获取绑定路径(更新于07/27)

//to access path - you can directly use the binding object
var binding = this.GetBinding(TextProperty);
var path = binding?.Path;

太好了。我以前做过这种事情。Xamarin团队喜欢无缘由地隐藏一些东西。 - Christian Findlay
会测试一下。 - Christian Findlay
2
也许可以添加一些说明如何获取BindableProperty?如果有人在寻找,它来自静态的 Entry,如 _associatedObject.GetBinding(Entry.TextProperty)。 - Andrey

1

改进Sharada Gururaj的解决方案:

public static class BindingObjectExtensions
{
    private static MethodInfo _bindablePropertyGetContextMethodInfo = typeof(BindableObject).GetMethod("GetContext", BindingFlags.NonPublic | BindingFlags.Instance);
    private static FieldInfo _bindablePropertyContextBindingFieldInfo;

    public static Binding GetBinding(this BindableObject bindableObject, BindableProperty bindableProperty)
    {
        object bindablePropertyContext = _bindablePropertyGetContextMethodInfo.Invoke(bindableObject, new[] { bindableProperty });

        if (bindablePropertyContext != null)
        {
            FieldInfo propertyInfo = _bindablePropertyContextBindingFieldInfo = 
                _bindablePropertyContextBindingFieldInfo ?? 
                    bindablePropertyContext.GetType().GetField("Binding");

            return (Binding) propertyInfo.GetValue(bindablePropertyContext);
        }

        return null; 
}

我的解决方案有以下改进:
  1. 通过反射缓存获取的对象(提高性能)
  2. 删除不必要的空值检查
  3. 直接使用反射,不需要使用IntrospectionExtensions
  4. 不需要GetBindingExpression方法(可以从Binding类中检索所有与绑定相关的信息)

嗨,伊戈尔,欢迎来到StackOverflow,你觉得能否添加一些解释,说明为什么这个答案是一个改进?它是否使用了更新的API,提供了更多的功能等。 - sedders123
你好 sedders123,我的解决方案有以下改进: 1)通过反射获取对象的缓存(提高性能) - Igor Buchelnikov
  1. 我移除了不必要的空值检查。
  2. 我直接使用反射,使用IntrospectionExtensions是不必要的。
  3. GetBindingExpression方法是不需要的(所有关于绑定的信息都可以从Binding类中检索)。
- Igor Buchelnikov
太棒了 :) 你能否编辑你的答案,包括这些信息?将其添加到答案中可以确保未来的用户轻松查看为什么这是一个不同且可能更好的解决方案,而不是其他任何答案。 - sedders123

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