Xamarin 表单 - GetBindingExpression

Xamarin Forms - GetBindingExpression

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

例如:

var selectedItemBindingExpression = GetBindingExpression(SelectedItemProperty);

但是,Xamarin Forms 中似乎没有等效项。有没有办法从 Xamarin Forms 中的 BindableProperty 属性 获取绑定表达式?

我认为 Xamarin.Forms 中没有任何 public 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;

改进了 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 class)
  5. 中检索绑定