0

I want to write a generic test that I can run without a WPF application and without a TraceLogger (listener).

The generic Test is suppost to compare an Interface with the bindings of a UserControl to see if there are missing or too many bindings.

ivm is an interface type for a viewmodel v is a view

v is supposed to bind to 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);

I can get a list of names that I bind to under certain conditions using code that looks like the one below. Where a listener listens to binding errors.

        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

I want to replace that with code that inspects a usercontrol and delivers all the binding names. I can not see how I would get all the bindings from a user control. I need some kind of starting point.

So in essence i look for an implementation that delivers the property names of bindings or complete binding paths. Is there a way to get that Information from a 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;
    }
Johannes
  • 6,490
  • 10
  • 59
  • 108
  • You will need to iterate through all child elements of the UserControl and get the binding expressions for each dependency property. Something like this: https://stackoverflow.com/questions/3586870/retrieve-all-data-bindings-from-wpf-window – mm8 Aug 10 '17 at 12:21
  • @mm8 I tried that solution but it finds no children. Neither using LogicalTreeHelper nor VisualTreeHelper. I think it may be connected to WPF not running. My context is an nunit application. – Johannes Aug 10 '17 at 14:20

1 Answers1

0

The method GetLocalValueEnumerator is what I was looking for. I just did not get how to use it right away. Here is an example implementation:

    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;
    }
Johannes
  • 6,490
  • 10
  • 59
  • 108