【问题标题】:Creating WPF bindings with expressions and reflection使用表达式和反射创建 WPF 绑定
【发布时间】:2018-11-30 14:39:37
【问题描述】:

我正在尝试简化将 WPF 控件绑定到我项目中的属性的过程。我希望能够以类似于以下方式调用该方法:

MyList.Bind( x => x.ItemsSource, App.Globals.ItemManager.Items );

我编写了一个扩展方法,该方法扩展了DependencyObject,并从给定的PropertyInfo(如果存在)正确解析DependencyProperty。现在,我需要从 sourceProperty 解析父对象,以便为正确的属性生成路径。

我的问题是,由于我将sourceProperty作为对象传递,似乎没有办法使用反射来获取父级的实例,也没有办法获取属性的PropertyInfo。我想保持参数列表尽可能干净并尽可能接近上面的示例,但如果没有解决方法,添加参数就可以了。

这是我当前的代码:

public static class BindingExtensions
{

  public static void Bind<TControl, TProperty>(
     this TControl control,
     Expression<Func<TControl, TProperty>> controlPropertyExpression,
     object sourceProperty )
     where TControl : DependencyObject
  {
     // Get DependencyProperty of control
     var controlPropertyInfo = controlPropertyExpression.GetPropertyInfo();
     var controlDependencyProperty = GetDependencyPropertyFromProperty( controlPropertyInfo );

     if( controlDependencyProperty == null )
        throw new ArgumentException(
           $"Could not resolve DependencyProperty for '{controlPropertyInfo.Name}' " +
           $"in class {controlPropertyInfo.ReflectedType}." );

     // Determine source object and path
     // TODO:
     //   var source = {parent instance of sourceProperty}
     //   var path = {name of sourceProperty}

     // Bind

     return;
  }

  public static IEnumerable<FieldInfo> GetDependencyPropertiesFromType( Type controlType )
  {
     var properties = controlType
        .GetFields( BindingFlags.Static | BindingFlags.Public )
        .Where( x => x.FieldType == typeof( DependencyProperty ) );

     if( controlType.BaseType != null )
        properties = properties.Union( GetDependencyPropertiesFromType( controlType.BaseType ) );

     return properties;
  }

  public static FieldInfo GetDependencyPropertyFromProperty( PropertyInfo propertyInfo, Type controlType = null )
  {
     if( controlType == null )
        controlType = propertyInfo.ReflectedType;

     var property = controlType
        .GetFields( BindingFlags.Static | BindingFlags.Public )
        .FirstOrDefault( x =>
            x.FieldType == typeof( DependencyProperty ) &&
            ((DependencyProperty)x.GetValue( null )).Name == propertyInfo.Name );

     if( property == null && controlType.BaseType != null )
        return GetDependencyPropertyFromProperty( propertyInfo, controlType.BaseType );

     return property;
  }

}

【问题讨论】:

  • @Clemens 是的,这是问题的一部分。我可以传入 byref,但我仍然需要一种方法来使用反射来获取所需的信息。
  • 除了属性名称之外,您还需要什么来创建绑定路径?只需传递 nameof(App.Globals.ItemManager.Items) 和源对象即可。

标签: c# .net wpf data-binding


【解决方案1】:

这其实很简单:

public static void Bind(
    this DependencyObject obj, DependencyProperty property, object source, string path)
{
    BindingOperations.SetBinding(obj, property, new Binding
    {
        Source = source,
        Path = new PropertyPath(path)
    });
}

用法:

MyList.Bind(
    ItemsControl.ItemsSourceProperty,
    itemManagerInstance,
    nameof(App.Globals.ItemManager.Items));

【讨论】:

    猜你喜欢
    • 2017-04-22
    • 2018-09-02
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多