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;
}
我的解决方案有以下改进:
- 缓存通过反射获得的对象(提高性能)
- 删除了不必要的空检查
- 直接使用反射,IntrospectionExtensions的使用是
不必要
- 不需要 GetBindingExpression 方法(关于
可以从 Binding class)
中检索绑定
在 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;
}
我的解决方案有以下改进:
- 缓存通过反射获得的对象(提高性能)
- 删除了不必要的空检查
- 直接使用反射,IntrospectionExtensions的使用是 不必要
- 不需要 GetBindingExpression 方法(关于 可以从 Binding class) 中检索绑定