0

I'm currently trying to bind an array element from a class to a text box without success.

class Test{
   ...
   string[] toto = new string[]{"element1"};
}

Test test;
void form_load()
{
   test = new Test();
   textBox1.DataBinding.Add("Text", test, "toto(0)");
}

(I tried as discussed here : Winforms Databinding to element in array)

But I get :

System.ArgumentException: 'Cannot bind to the property or column Requires(0) on the DataSource. Parameter name: dataMember'

If I bind it like this:

checkBox2.DataBindings.Add(new Binding("Checked", config.Requires[0], ""));

It works but I can't implement INotifyPropertyChanged for updating the form on change perform by the code.

Does anyone have any idea?

Edit: After binding, the form should be updated when the element of the array is updated.

6
  • Not sure if this helps, but this answer binding a checkbox passes an event argument as well. Commented Jan 7, 2020 at 17:47
  • data binding a control to an element of an array at specific index Commented Jan 7, 2020 at 20:13
  • @ourmandave doesn't work :/. Commented Jan 8, 2020 at 8:12
  • @RezaAghaei working but it doesn't update on the form when I edit the value in code. I don't know how to implement INotifyPropertyChanged there :(. Commented Jan 8, 2020 at 8:12
  • It means an array of string is not a good data structure for you. Commented Jan 8, 2020 at 10:35

2 Answers 2

0

Quite possibly there is a better way to do this, but what you could do is create an instance of BindingSource for each element in the array, set the BindingSource.Position property, then set that as the binding for the TextBox.

Edit: Made the Data Binding 2-way... changing the value in the control updates the object, changing the value from the object changes the control.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Test
{
   public class Foo
   {
      public Foo()
      {
         Items = new BindingList<string>();
      }

      public IList<string> Items { get; private set; }
   }

   static class Program
   {
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);

         _dataSource.Items.Add("Value");
         _dataSource.Items.Add("Value 2");
         _dataSource.Items.Add("Value 3");

         var frm = new Form();

         var flp = new FlowLayoutPanel
         {
            Dock = DockStyle.Fill,
            FlowDirection = FlowDirection.TopDown
         };

         for (int i = 0; i < _dataSource.Items.Count; i++)
         {
            var bs = new BindingSource(_dataSource, "Items");
            bs.Position = i;
            var tb = new TextBox();
            tb.DataBindings.Add("Text", bs, "");
            flp.Controls.Add(tb);
         }
         frm.Controls.Add(flp);

         var btn = new Button()
         {
            Text = "Show Object's Values",
            Dock = DockStyle.Bottom
         };
         btn.Click += btn_Click;
         frm.Controls.Add(btn);

         var btn2 = new Button()
         {
            Text = "Change Object's Values",
            Dock = DockStyle.Bottom
         };
         btn2.Click += btn2_Click;
         frm.Controls.Add(btn2);

         Application.Run(frm);
      }

      static void btn_Click(object sender, EventArgs e)
      {
         MessageBox.Show(string.Join(Environment.NewLine, _dataSource.Items.ToArray()));
      }

      static void btn2_Click(object sender, EventArgs e)
      {
         var rng = new Random();
         for (int i = 0; i < _dataSource.Items.Count; i++)
         {
            var b = new byte[8];
            rng.NextBytes(b);
            _dataSource.Items[i] = Convert.ToBase64String(b);
         }
      }

      static Foo _dataSource = new Foo();
   }
}
Sign up to request clarification or add additional context in comments.

4 Comments

this way to set the position is definitively more clear than described here: stackoverflow.com/a/38325943/12530707. But the problem of "I change the value in my code and it doesn't update on form" still remains :/. PS: from where is coming the _dataSource variable in your second code?
_dataSource is a static field on the Program class declared right before the closing curly brace of the Program class. static Foo _dataSource = new Foo().
I made an edit to make the data binding two way by changing the type of Foo.Items to IList so I could use an indexer to change the values, then setting it to an instance of BindingList<string> instead of List<string> in the constructor for Foo.
Ok, now I understand, you encapsulate the values in a BindingList element that probably already implement the INotifyPropertyChanged interface. Perfect! Thank you. :)
0

You could create a property as follows:

private string _element1;
public string Element1
{
  get
  {
    return _element1;
  }
  set 
  {
   element1 = value;
    OnPropertyChanged(nameof(Element1));
  }
}

Set it as: Element1 = config.Requires[0]; And then use it to set the TextBox as follows: checkBox2.DataBindings.Add(new Binding("Checked", Element1, ""));

1 Comment

Yes that is working but there is not another way cleaner than creating a properties for each value of my array? With an array of 100 value would involve to create 100 properties :/.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.