从 UserControl 获取绑定列表

Get a list of Bindings from a UserControl

我想编写一个通用测试,我可以 运行 没有 WPF 应用程序和 TraceLogger(侦听器)。

通用测试支持将接口与用户控件的绑定进行比较,以查看是否缺少绑定或绑定过多。

ivm 是视图模型的接口类型 v 是一个视图

v 应该绑定到 ivm。

        var names_binding = listener.bindNames.Distinct(); //this is what i want to get rid of.
        var names_interface = ivm.GetProperties().Select(prop => prop.Name).Distinct();
        var tooMany = names_interface.Except(names_binding);
        var tooFew = names_binding.Except(names_interface);

我可以使用如下所示的代码获取在特定条件下绑定到的名称列表。其中 listener 侦听绑定错误。

        object obj = new object();
        T_V view = new T_V();
        view.DataContext = obj; // empty object - all binding will fail
        DoEvents(); // Do Events pumps WPF so binding happens

我想用检查用户控件并提供所有绑定名称的代码替换它。我看不到如何从用户控件获取所有绑定。我需要某种起点。

因此,从本质上讲,我正在寻找一种实现,它提供 属性 绑定名称或完整的绑定路径。有没有办法从 UserControl 获取该信息?

    public IEnumerable<string> GetBindingPaths<T_V>() where T_V : UserControl, new()
    {
        var ret = Enumerable.Empty<string>();
        T_V view = new T_V();
        //// view.GetBindingExpression ???
        //// view.GetLocalValueEnumerator ???
        return ret;
    }

GetLocalValueEnumerator 方法正是我要找的。我只是不知道如何立即使用它。这是一个示例实现:

    private IEnumerable<string> GetBindingPropertyNames(DependencyObject target)
    {
        return from path in GetBindingPaths(target) select path.Split('.').First();
    }

    private IEnumerable<string> GetBindingPaths(DependencyObject target)
    {
        var ret = new List<string>();
        LocalValueEnumerator lve = target.GetLocalValueEnumerator();

        while (lve.MoveNext())
        {
            LocalValueEntry entry = lve.Current;
            if (entry.Value is DependencyObject)
            {
                ret.AddRange(GetBindingPaths(entry.Value as DependencyObject));
            }

            if (BindingOperations.IsDataBound(target, entry.Property))
            {
                Binding binding = (entry.Value as BindingExpression).ParentBinding;
                ret.Add(binding.Path.Path);
            }
        }
        return ret;
    }