Unit test for bug #821.
[mono.git] / mcs / class / Managed.Windows.Forms / Test / System.Windows.Forms / BindingTest.cs
index 33d9b493889a2e6df4ad7cffa454d232808fd148..17e6cce2a2a1df19ad77c1e4c7635b9ccb164c4a 100644 (file)
 using System;
 using System.Data;
 using System.Collections;
+using System.Globalization;
 using System.Windows.Forms;
 
 using NUnit.Framework;
 
-namespace MonoTests.System.Windows.Forms {
+namespace MonoTests.System.Windows.Forms.DataBinding {
 
        [TestFixture]
-       public class BindingTest {
-
-               [SetUp]
-               protected virtual void SetUp ()
-               {
-               }
-
-               [TearDown]
-               protected virtual void TearDown ()
-               {
-               }
-
+       public class BindingTest : TestHelper {
+               
                [Test]
                public void CtorTest ()
                {
@@ -61,6 +52,14 @@ namespace MonoTests.System.Windows.Forms {
 
                        Assert.AreSame (b.PropertyName, prop, "ctor5");
                        Assert.AreSame (b.DataSource, data_source, "ctor6");
+
+#if NET_2_0
+                       Assert.AreEqual (false, b.FormattingEnabled, "ctor7");
+                       Assert.AreEqual (String.Empty, b.FormatString, "ctor8");
+                       Assert.IsNull (b.FormatInfo, "ctor9");
+                       Assert.IsNull (b.NullValue, "ctor10");
+                       Assert.AreEqual (Convert.DBNull, b.DataSourceNullValue, "ctor11");
+#endif
                }
 
                [Test]
@@ -72,6 +71,47 @@ namespace MonoTests.System.Windows.Forms {
                        Assert.IsNull (b.DataSource, "ctornull2");
                }
 
+               [Test]
+               public void CtorEmptyProperty ()
+               {
+                       Binding b = new Binding ("Text", 6, String.Empty);
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       c.DataBindings.Add (b);
+                       Assert.AreEqual ("6", c.Text, "A1");
+               }
+
+               [Test]
+               public void BindingManagerBaseTest ()
+               {
+                       if (TestHelper.RunningOnUnix) {
+                               Assert.Ignore ("Fails at the moment");
+                       }
+
+                       Control c1 = new Control ();
+                       Control c2 = new Control ();
+                       Binding binding;
+
+                       c1.BindingContext = new BindingContext ();
+                       c2.BindingContext = c1.BindingContext;
+
+                       binding = c2.DataBindings.Add ("Text", c1, "Text");
+
+                       Assert.IsNull (binding.BindingManagerBase, "1");
+
+                       c1.CreateControl ();
+                       c2.CreateControl ();
+
+                       Assert.IsNull (binding.BindingManagerBase, "2");
+
+                       c2.DataBindings.Remove (binding);
+                       binding = c2.DataBindings.Add ("Text", c1, "Text");
+
+                       Assert.IsTrue (binding.BindingManagerBase != null, "3");
+               }
+
                [Test]
                /* create control and set binding context */
                public void BindingContextChangedTest ()
@@ -86,7 +126,6 @@ namespace MonoTests.System.Windows.Forms {
                }
 
                [Test]
-               [Category ("NotWorking")]
                /* create control and show control */
                public void BindingContextChangedTest2 ()
                {
@@ -103,7 +142,7 @@ namespace MonoTests.System.Windows.Forms {
 #else
                        Assert.AreEqual (2, eventcount, "A1");
 #endif
-            f.Dispose();
+                       f.Dispose();
                }
 
                [Test]
@@ -124,9 +163,36 @@ namespace MonoTests.System.Windows.Forms {
                        f.Dispose ();
                }
 
+               [Test]
+               public void BindingContextChangedTest4 ()
+               {
+                       Form f = new Form ();
+                       f.ShowInTaskbar = false;
+
+                       ContainerControl cc = new ContainerControl ();
+
+                       Control c = new Control ();
+                       f.Controls.Add (cc);
+                       cc.Controls.Add (c);
+
+                       c.BindingContextChanged += new EventHandler (Event_Handler1);
+                       cc.BindingContextChanged += new EventHandler (Event_Handler1);
+                       f.BindingContextChanged += new EventHandler (Event_Handler1);
+
+                       eventcount = 0;
+                       f.Show ();
+#if NET_2_0
+                       Assert.AreEqual (5, eventcount, "A1");
+#else
+                       Assert.AreEqual (8, eventcount, "A1");
+#endif
+                       f.Dispose ();
+               }
+
                int eventcount;
                public void Event_Handler1 (object sender, EventArgs e)
                {
+                       //Console.WriteLine (sender.GetType());
                        //Console.WriteLine (Environment.StackTrace);
                        eventcount++;
                }
@@ -162,6 +228,572 @@ namespace MonoTests.System.Windows.Forms {
                        Assert.AreEqual ("Text", b.PropertyName, "6");
                        Assert.AreEqual ("Name", b.BindingMemberInfo.BindingField, "7");
                }
+
+               [Test]
+               public void DataSourceNullTest ()
+               {
+                       ChildMockItem item = new ChildMockItem ();
+                       Control c = new Control ();
+                       c.Tag = null;
+                       item.ObjectValue = null;
+
+                       c.DataBindings.Add ("Tag", item, "ObjectValue");
+
+                       Form f = new Form ();
+                       f.Controls.Add (c);
+
+                       f.Show (); // Need this to init data binding
+
+                       Assert.AreEqual (DBNull.Value, c.Tag, "1");
+                       
+                       f.Dispose ();
+                       
+               }
+
+               // For this case to work, the data source property needs
+               // to have an associated 'PropertyChanged' event.
+               [Test]
+               public void DataSourcePropertyChanged ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       Binding binding = new Binding ("Text", item, "Text");
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       item.Text = "B";
+                       Assert.AreEqual ("B", c.Text, "#B1");
+               }
+
+               [Test]
+               public void DataSourcePropertyChanged_Original ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       Binding binding = new Binding ("Text", item, "Text");
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       item.Text = "B";
+                       Assert.AreEqual ("B", c.Text, "#B1");
+               }
+
+               [Test]
+               public void DataSourcePropertyChanged_Original_BadName ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       Binding binding = new Binding ("Text", item, "xxxxxxTextXXXXX");
+
+                       try {
+                               c.DataBindings.Add (binding);
+                               Assert.Fail ("exc1");
+                       } catch (ArgumentException ex) {
+                               Assert.AreEqual ("dataMember", ex.ParamName, "ex.ParamName"); // (test is not locale dependent)
+                       }
+               }
+
+               [Test]
+               public void DataSourcePropertyChanged_OneDeep ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       One parent = new One ();
+                       parent.MockItem = item;
+                       Binding binding = new Binding ("Text", parent, "MockItem.Text");
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       item.Text = "B";
+                       Assert.AreEqual ("B", c.Text, "#B1");
+               }
+
+               [Test]
+               public void DataSourcePropertyChanged_ThreeDeep ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       One parent = new One ();
+                       parent.Two = new Two ();
+                       parent.Two.Three = new Three ();
+                       parent.Two.Three.MockItem = item;
+                       Binding binding = new Binding ("Text", parent, "Two.Three.MockItem.Text");
+
+                       c.DataBindings.Add (binding);
+                       Console.WriteLine ("c.Text: " + c.Text);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       item.Text = "B";
+                       Assert.AreEqual ("B", c.Text, "#B1");
+
+                       Assert.AreEqual (1, c.DataBindings.Count, "c.DataBindings.Count");
+                       BindingMemberInfo bmi = c.DataBindings[0].BindingMemberInfo;
+                       Assert.AreEqual ("Two.Three.MockItem", bmi.BindingPath, "bmi.BindingPath");
+                       Assert.AreEqual ("Two.Three.MockItem.Text", bmi.BindingMember, "bmi.BindingMember");
+                       Assert.AreEqual ("Text", bmi.BindingField, "bmi.BindingField");
+               }
+
+               [Test]
+               public void DataSourcePropertyChanged_DataSet ()
+               {
+                       DataSet ds = new DataSet ();
+
+                       DataTable table1 = new DataTable ("Customers");
+                       table1.Columns.Add ("Id", typeof (int));
+                       table1.Columns.Add ("Name", typeof (string));
+                       table1.Rows.Add (new object[] {3, "customer1"});
+                       table1.Rows.Add (new object[] {7, "customer2"});
+                       ds.Tables.Add (table1);
+
+                       DataTable table2 = new DataTable ("Orders");
+                       table2.Columns.Add ("OrderId", typeof (int));
+                       table2.Columns.Add ("CustomerId", typeof (int));
+                       table2.Rows.Add (new object[] {56, 7});
+                       table2.Rows.Add (new object[] {57, 3});
+                       ds.Tables.Add (table2);
+
+                       DataRelation relation = new DataRelation ("CustomerOrders", table1.Columns ["Id"],
+                                       table2.Columns ["CustomerId"]);
+                       ds.Relations.Add (relation);
+
+                       Control ctrl = new Control ();
+                       ctrl.BindingContext = new BindingContext ();
+                       ctrl.CreateControl ();
+
+                       ctrl.DataBindings.Add ("Text", ds, "Customers.CustomerOrders.OrderId");
+                       Assert.AreEqual ("57", ctrl.Text, "A1");
+               }
+
+               [Test]
+               public void DataSourcePropertyDifferentType ()
+               {
+                       Exception exc = new Exception (String.Empty, new ArgumentNullException ("PARAM"));
+
+                       // The type of the property is Exception, but we know that the value
+                       // is actually an ArgumentException, thus specify the ParamName property
+                       Control ctrl = new Control ();
+                       ctrl.BindingContext = new BindingContext ();
+                       ctrl.CreateControl ();
+
+                       ctrl.DataBindings.Add ("Text", exc, "InnerException.ParamName");
+                       Assert.AreEqual ("PARAM", ctrl.Text, "A1");
+               }
+
+               [Test]
+               public void IsBindingTest ()
+               {
+                       MockItem [] items = new MockItem [] { new MockItem ("A", 0) };
+                       Binding binding = new Binding ("Text", items, "Text");
+                       Binding binding2 = new Binding ("Text", items [0], "Text");
+                       Assert.IsFalse (binding.IsBinding, "#A1");
+                       Assert.IsFalse (binding2.IsBinding, "#A2");
+
+                       Control c = new Control ();
+                       Control c2 = new Control ();
+                       c.DataBindings.Add (binding);
+                       c2.DataBindings.Add (binding2);
+                       Assert.IsFalse (binding.IsBinding, "#B1");
+                       Assert.IsFalse (binding2.IsBinding, "#B2");
+
+                       c.CreateControl ();
+                       c2.CreateControl ();
+                       Assert.IsFalse (binding.IsBinding, "#C1");
+                       Assert.IsFalse (binding2.IsBinding, "#C2");
+
+                       Form form = new Form ();
+                       form.ShowInTaskbar = false;
+                       form.Controls.Add (c);
+                       form.Controls.Add (c2);
+                       Assert.IsTrue (binding.IsBinding, "#D1");
+                       Assert.IsTrue (binding2.IsBinding, "#D2");
+
+                       form.Show ();
+
+                       // Important part -
+                       // IsBinding is true ALWAYS with PropertyManager, even when
+                       // ResumeBinding has been called
+                       //
+                       CurrencyManager curr_manager = (CurrencyManager)form.BindingContext [items];
+                       PropertyManager prop_manager = (PropertyManager)form.BindingContext [items [0]];
+                       curr_manager.SuspendBinding ();
+                       prop_manager.SuspendBinding ();
+                       Assert.IsFalse (binding.IsBinding, "#E1"); 
+                       Assert.IsTrue (binding2.IsBinding, "#E2");
+
+                       curr_manager.ResumeBinding ();
+                       prop_manager.ResumeBinding ();
+                       Assert.IsTrue (binding.IsBinding, "#F1");
+                       Assert.IsTrue (binding2.IsBinding, "#F2");
+
+                       form.Dispose ();
+               }
+
+#if NET_2_0
+               [Test]
+               public void ReadValueTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       ChildMockItem item = new ChildMockItem ();
+                       item.ObjectValue = "A";
+                       Binding binding = new Binding ("Tag", item, "ObjectValue");
+                       binding.ControlUpdateMode = ControlUpdateMode.Never;
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual (null, c.Tag, "#A1");
+
+                       item.ObjectValue = "B";
+                       Assert.AreEqual (null, c.Tag, "#B1");
+
+                       binding.ReadValue ();
+                       Assert.AreEqual ("B", c.Tag, "#C1");
+
+                       item.ObjectValue = "C";
+                       binding.ReadValue ();
+                       Assert.AreEqual ("C", c.Tag, "#D1");
+                       
+                       c.Dispose();
+               }
+
+               [Test]
+               public void WriteValueTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ();
+                       item.Text = "A";
+                       Binding binding = new Binding ("Text", item, "Text");
+                       binding.DataSourceUpdateMode = DataSourceUpdateMode.Never;
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       c.Text = "B";
+                       Assert.AreEqual ("A", item.Text, "#B1");
+
+                       binding.WriteValue ();
+                       Assert.AreEqual ("B", item.Text, "#C1");
+               }
+
+               [Test]
+               public void BindableComponentTest ()
+               {
+                       Control c = new Control ();
+
+                       MockItem item = new MockItem (String.Empty, 0);
+                       Binding binding = new Binding ("Text", item, "Text");
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual (c, binding.Control, "#A1");
+                       Assert.AreEqual (c, binding.BindableComponent, "#A2");
+
+                       // 
+                       // Now use IBindableComponent - update binding when property changes
+                       // since ToolStripItem doesn't have validation at all
+                       //
+                       BindableToolStripItem toolstrip_item = new BindableToolStripItem ();
+                       toolstrip_item.BindingContext = new BindingContext ();
+                       Binding binding2 = new Binding ("Text", item, "Text");
+                       binding2.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
+
+                       item.Text = "A";
+                       toolstrip_item.DataBindings.Add (binding2);
+                       Assert.AreEqual (null, binding2.Control, "#B1");
+                       Assert.AreEqual (toolstrip_item, binding2.BindableComponent, "#B2");
+                       Assert.AreEqual (item.Text, toolstrip_item.Text, "#B3");
+
+                       toolstrip_item.Text = "B";
+                       Assert.AreEqual (toolstrip_item.Text, item.Text, "#C1");
+               }
+
+               [Test]
+               public void ControlUpdateModeTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       Binding binding = new Binding ("Text", item, "Text");
+                       binding.ControlUpdateMode = ControlUpdateMode.Never;
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual (String.Empty, c.Text, "#A1");
+
+                       item.Text = "B";
+                       Assert.AreEqual (String.Empty, c.Text, "#B1");
+               }
+
+               [Test]
+               public void DataSourceUpdateModeTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ("A", 0);
+                       Binding binding = new Binding ("Text", item, "Text");
+                       binding.DataSourceUpdateMode = DataSourceUpdateMode.Never;
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ("A", c.Text, "#A1");
+
+                       c.Text = "B";
+                       Assert.AreEqual ("A", item.Text, "#B1");
+
+                       binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
+                       Assert.AreEqual ("A", item.Text, "#C1");
+
+                       c.Text = "C";
+                       Assert.AreEqual ("C", item.Text, "#D1");
+
+                       // This requires a Validation even, which we can't test
+                       // by directly modifying the property
+                       binding.DataSourceUpdateMode = DataSourceUpdateMode.OnValidation;
+
+                       c.Text = "D";
+                       Assert.AreEqual ("C", item.Text, "#E1");
+               }
+
+               [Test]
+               public void DataSourceNullValueTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       ChildMockItem item = new ChildMockItem ();
+                       item.ObjectValue = "A";
+                       Binding binding = new Binding ("Tag", item, "ObjectValue");
+                       binding.DataSourceNullValue = "NonNull";
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual (c.Tag, "A", "#A1");
+
+                       // Since Tag property doesn't have a 
+                       // TagChanged event, we need to force an update
+                       c.Tag = null;
+                       binding.WriteValue ();
+                       Assert.AreEqual (item.ObjectValue, "NonNull", "#B1");
+               }
+
+               [Test]
+               public void NullValueTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       DataTable table = new DataTable ();
+                       table.Columns.Add ("Name", typeof (string));
+                       table.Columns.Add ("Id", typeof (int));
+                       table.Rows.Add (null, DBNull.Value);
+
+                       Binding binding = new Binding ("Tag", table, "Name");
+                       Binding binding2 = new Binding ("Width", table, "Id");
+                       binding.FormattingEnabled = true;
+                       binding.NullValue = "non-null";
+                       binding2.FormattingEnabled = true;
+                       binding2.NullValue = 101;
+
+                       c.Width = 99;
+                       c.DataBindings.Add (binding);
+                       c.DataBindings.Add (binding2);
+
+                       Assert.AreEqual ("non-null", c.Tag, "#A1");
+                       Assert.AreEqual (101, c.Width, "#A2");
+               }
+
+               [Test]
+               public void FormattingEnabledTest ()
+               {
+                       Control c = new Control ();
+                       c.BindingContext = new BindingContext ();
+                       c.CreateControl ();
+
+                       MockItem item = new MockItem ();
+                       item.Value = 666;
+                       Binding binding = new Binding ("Text", item, "Value");
+                       binding.FormattingEnabled = true;
+                       binding.FormatString = "p";
+
+                       c.DataBindings.Add (binding);
+                       Assert.AreEqual ((666).ToString ("p"), c.Text, "#A1");
+
+                       binding.FormatString = "c";
+                       Assert.AreEqual ((666).ToString ("c"), c.Text, "#B1");
+                       Console.WriteLine (c.Text);
+
+                       binding.FormattingEnabled = false;
+                       Assert.AreEqual ((666).ToString (), c.Text, "#C1");
+               }
+
+               [Test]
+               public void FormatStringTest ()
+               {
+                       Binding binding = new Binding ("Text", null, "Text");
+                       binding.FormatString = null;
+
+                       Assert.AreEqual (String.Empty, binding.FormatString, "#A1");
+               }
+#endif
+
+       }
+
+       class ChildMockItem : MockItem
+       {
+               object value;
+
+               public ChildMockItem ()
+                       : base (null, 0)
+               {
+               }
+
+               public object ObjectValue
+               {
+                       get
+                       {
+                               return value;
+                       }
+                       set
+                       {
+                               this.value = value;
+                       }
+               }
+       }
+
+#if NET_2_0
+       class BindableToolStripItem : ToolStripItem, IBindableComponent
+       {
+               ControlBindingsCollection data_bindings;
+               BindingContext binding_context;
+
+               public ControlBindingsCollection DataBindings {
+                       get {
+                               if (data_bindings == null)
+                                       data_bindings = new ControlBindingsCollection (this);
+
+                               return data_bindings;
+                       }
+               }
+
+               public BindingContext BindingContext
+               {
+                       get {
+                               return binding_context;
+                       }
+                       set {
+                               binding_context = value;
+                       }
+               }
+       }
+#endif
+
+       class One
+       {
+               //----
+               //private global::System.Collections.Generic.IList<Two> m_twoList
+               //    = new global::System.Collections.Generic.List<Two> ();
+               //
+               //public global::System.Collections.Generic.IList<Two> TwoList
+               //{
+               //    get { return m_twoList; }
+               //}
+
+               //----
+               private Two m_two;
+
+               public Two Two
+               {
+                       get { return m_two; }
+                       set { m_two = value; }
+               }
+       
+               //----
+               private MockItem m_MockItem;
+
+               public MockItem MockItem
+               {
+                       get { return m_MockItem; }
+                       set { m_MockItem = value; }
+               }
+       
+               //----
+               public override string ToString ()
+               {
+                       return "!!! ToString on One !!!";
+               }
+       }
+
+       class Two
+       {
+               //private global::System.Collections.Generic.IList<MockItem> m_MockItemList
+               //    = new global::System.Collections.Generic.List<MockItem> ();
+               //
+               //public global::System.Collections.Generic.IList<MockItem> MockItemList
+               //{
+               //    get { return m_MockItemList; }
+               //}
+
+               //----
+               private MockItem m_MockItem;
+
+               public MockItem MockItem
+               {
+                       get { return m_MockItem; }
+                       set { m_MockItem = value; }
+               }
+
+               private Three m_Three;
+
+               public Three Three
+               {
+                       get { return m_Three; }
+                       set { m_Three = value; }
+               }
+
+               public override string ToString ()
+               {
+                       return "!!! ToString on Two !!!";
+               }
+       }
+
+       class Three
+       {
+               private MockItem m_MockItem;
+
+               public MockItem MockItem
+               {
+                       get { return m_MockItem; }
+                       set { m_MockItem = value; }
+               }
+
+               public override string ToString ()
+               {
+                       return "!!! ToString on Three !!!";
+               }
        }
 
 }