Welcome to Habanero Land!   Register  |  Login
You are here:   Blogs
  So, why do you need to register to download Habanero and access the additional materials? 
The success of any open source project is based on the community built around it. So go ahead, register / login and get involved!
Dec
16
Thu
Posted By Andrew on Thursday, December 16, 2010
197 Views


This is the fourth blog in a series of blogs I have put together whilst trying to find a solution for unit testing WPF Bindings.

Just a quick recap of exactly what I am trying to achieve.

  • I want to be able to test the bindings between a business object and the control that is used to display the property of a business object. At the moment my aim is to achieve this with very simple bindings.
  • The test should pass when the binding exists for a given property on the business object
  • The test should fail if the binding name is incorrectly spelled
  • The test should fail if the binding is not found at all

At last I have found something promising. After more trawling of the internet I stumbled across some code that Nigel Spencer has on his blog (http://blog.spencen.com/2008/05/02/how-to-get-a-list-of-bindings-in-wpf.aspx). This looks promising.

I copied and pasted the code into my test project as is. After a bit of fiddling to create a ValidationBindingContextClass and then some more fiddling to get my head around exactly what parameters I needed, I was ready to roll. Bingo! When the bindings are correct the tests pass and when the bindings are incorrect (don’t exist or there is a typo) they fail.

        private static ValidationBindingContext GetBindingForProperty(Type boundType, 
							string boundPropertyName, FrameworkElement root)
        {
            foreach (FrameworkElement element in LogicalTreeHelper.GetChildren(root).OfType())
            {
                FieldInfo[] properties = element.GetType().GetFields(BindingFlags.Public | 
						BindingFlags.GetProperty | 
						BindingFlags.Static | 
						BindingFlags.FlattenHierarchy);
                foreach (FieldInfo field in properties)
                {
                    if (field.FieldType == typeof(DependencyProperty))
                    {
                        DependencyProperty dp = (DependencyProperty)field.GetValue(null);
                        if (BindingOperations.IsDataBound(element, dp))
                        {
                            BindingExpression bindingExpression = BindingOperations.GetBindingExpression(element, dp);
                            if (boundType == bindingExpression.DataItem.GetType())
                            {
                                if (boundPropertyName == bindingExpression.ParentBinding.Path.Path)
                                {
                                    return new ValidationBindingContext(bindingExpression, element as UIElement);
                                }
                            }
                        }
                    }
                }
 
                // Not found so check all child elements
                ValidationBindingContext bindingContext = GetBindingForProperty(boundType, boundPropertyName, element);
                if (bindingContext != null) return bindingContext;
            }
            return null;
        }


    internal class ValidationBindingContext
    {
        public BindingExpression Expression { get; private set; }
        public UIElement Element { get; private set; }
 
        public ValidationBindingContext(BindingExpression expression, UIElement element)
        {
            Element = element;
            Expression = expression;
        }
    }

And here is the unit test. You will notice I have renamed the method to TestBindingForProperty.

        public void Test_MainWindow_Databindings2ndTry()
        {
            TestUtilsComputerPart.GetTestFactory().CreateManySavedBusinessObject(10);
 
            //AvalonTestRunner.RunDataBindingTests(new ComputerPartDetail());
 
            var partWindow = new MainWindow();
            partWindow.Show();
            try
            {
                //var partWindow = Window.GetWindow(new ComputerPartDetail());
 
                var desc = TestBindingForProperty(typeof(ComputerPart), "Description", partWindow);
                Assert.IsNotNull(desc);
 
                var price = TestBindingForProperty(typeof(ComputerPart), "Price", partWindow);
                Assert.IsNotNull(price);
 
                var stock = TestBindingForProperty(typeof(ComputerPart), "Stock", partWindow);
                Assert.IsNotNull(stock);
 
                var cost = TestBindingForProperty(typeof(ComputerPart), "Cost", partWindow);
                Assert.IsNotNull(cost);
 
            }
            finally
            {
                partWindow.Close();
            }           
 
        }

Yes, the test is not all that pretty, but at last I feel I am on my way. With a bit of thought and some re-factoring I am sure I can get the tests to look a whole lot better.

Categories

 Top Viewed
 Habanero Cloud
 Archive
 

This website is best viewed in Internet Explorer 7 & 8; Firefox 3.6.11; Opera 10.63; & Safari 4.