Привязка элемента управления к объекту против DataRow - PullRequest
0 голосов
/ 18 января 2019

Я написал пример кода, чтобы продемонстрировать свой вопрос. один привязан к объекту, а другой к DataRow:

Пример привязки к DataRow:

namespace WindowsFormsApplication1
{
    public partial class frmBindExample : Form
    {
        public frmBindExample()
        {
            InitializeComponent();
            InitForm();
        }



        private void InitForm()
        {
            //;; Init the list
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Id"));
            dt.Columns.Add(new DataColumn("Name"));
            dt.Rows.Add(new string[] { "5476", "Smith" });
            dt.Rows.Add(new string[] { "5477", "Marlin" });


            Label label1 = new Label() { Top = 130, Left = 10, Text = "Id of Smith is:" };
            this.Controls.Add(label1);

            //;; Bind two direction with TextBox. 
            TextBox textbox1 = new TextBox() { Top = 130, Left = 130, Width = 100 };
            this.Controls.Add(textbox1);
            textbox1.DataBindings.Add("Text", dt.Rows[0], "Id");


            //;; The binding system respose changing property value
            Button button1 = new Button() { Top = 160, Left = 10, Width = 200, Text = "Set Id=99 Directly by property" };
            this.Controls.Add(button1);
            button1.Click += (s, e) =>
            {
                dt.Rows[0]["Id"] = "99";
            };

            DataGridView dg = new DataGridView() { Top = 200, Left = 10 };
            this.Controls.Add(dg);
            dg.DataSource = dt;
        }


    }
}

Это выглядит так:

enter image description here

Как видите, привязка к TextBox не работает, как в следующем примере. Но когда я обновляю поле нажатием на кнопку, сетка данных немедленно обновляется:

enter image description here

Хорошо, теперь посмотрим, что пенька, если я вместо этого связываю Объект:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class frmBindExample : Form
    {
        public frmBindExample()
        {
            InitializeComponent();
            InitForm();
        }


        private void InitForm()
        {
            //;; Init the list
            List<Person> lst = new List<Person>();
            lst.Add(new Person() { Id = "5476", Name = "Smith" });
            lst.Add(new Person() { Id = "5477", Name = "Marlin" });


            Label label1 = new Label() { Top = 130, Left = 10, Text = "Id of Smith is:" };
            this.Controls.Add(label1);

            //;; Bind two direction with TextBox. 
            TextBox textbox1 = new TextBox() { Top = 130, Left = 130, Width = 100 };
            this.Controls.Add(textbox1);
            textbox1.DataBindings.Add("Text", lst[0], "Id");

            //;; The binding system respose changing property value
            Button button1 = new Button() { Top = 160, Left = 10, Width = 200, Text = "Set Id=99 Directly by property" };
            this.Controls.Add(button1);
            button1.Click += (s, e) =>
            {
                lst[0].Id = "99";
            };

            DataGridView dg = new DataGridView() { Top = 200, Left = 10 };
            this.Controls.Add(dg);
            dg.DataSource = lst;
        }

    }


    //;; The person class can bind any his property without any extra call fo change detection 
    public class Person
    {
        public string Id { get; set;}
        public string Name { get; set; }
    }
}

Теперь TextBox показывает значение Id, когда мы аспектируем. Но нажмите кнопку Set, чтобы не обновлять данные в DataGrid.

Итак, мой вопрос:

  1. Почему привязка TextBox не работает правильно в первом примере?
  2. Верно сказать, что автоматическое (без какого-либо дополнительного вызова для привязки do) распространение с источника на элемент управления происходит только с DataRow?

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Почему привязка TextBox не работает правильно в первом примере?

Это потому, что TypeDescriptor из DataRow не имеет свойства Id. Рассмотрим следующие правила:

  • При привязке данных к свойству элемента дескриптор типа элемента должен содержать свойство с таким именем.

  • При привязке данных к списку дескриптор типа элемента списка должен содержать свойство с таким именем.

Правда ли, что автоматическое (без какого-либо дополнительного вызова для привязки do) распространение с источника на элемент управления происходит только с DataRow?

Нет. Это не из-за типа DataRow. Это из-за INotifyPropertyChanged и IBindingList. Рассмотрим следующие правила:

  • При привязке данных к элементу управления, если элемент реализует INotifyPropertyChanged, пользовательский интерфейс будет обновляться сразу после обновления элемента.

  • При привязке данных к элементу управления списком, если элемент реализует INotifyPropertyChanged и список реализует IBindingList, пользовательский интерфейс будет обновляться сразу после обновления элемента или списка.

Дополнительная информация

То, что я описал выше вкратце, вы можете найти в Привязка данных Windows Forms . Я рекомендую прочитать следующие полезные документы:

0 голосов
/ 18 января 2019

Поскольку, может быть, описание этой процедуры в комментариях не очень хорошая идея, вот расширенная версия .

  • Определите BindingList или List<T> в качестве объекта хранения данных (я предпочитаю BindinList, но здесь IList будет выполнять эту работу в любом случае).
  • Определите BindingSource , который будет предоставлять уведомления об изменениях и управление валютой. Это значительно упрощает привязку элементов управления в WinForms.

  • Установите свойство BindingSource.DataSource для объекта, который предоставляет данные: здесь BindingList или IList.

  • Добавьте Binding к свойству TextBox.Text, которое будет связано со свойством источника данных (или, например, столбцом таблицы данных), установив DataSource значение Binding для BindingSource и значение DataMember для свойства (или столбца) источника данных, для которого свойство TextBox является связанным. Здесь свойство Id класса Inputs.
  • Подпишитесь на событие Parse TextBox Binding, чтобы обеспечить средства для проверки данных, введенных в TextBox, перед разрешением обновления источника данных. Если введенное значение не соответствует описанию (т.е. пользователь вводит буквы вместо цифр), мы можем вызвать, например, метод BindingSource.ResetCurrentItem , чтобы отменить обновление данных
  • Установите DataGridView.DataSource на BindingSource.

Вот что происходит, используя код, показанный здесь:

DataBindings BindingSource


Примечание
Я использую лямбду здесь, чтобы подписаться на событие Parse; Вы можете захотеть использовать отдельный обработчик, если вам нужно подписаться / отписаться на это событие более одного раза.

internal class Inputs
{
    public int Id { get; set; }
    public string Name { get; set; }
}

internal List<Inputs> InputData = new List<Inputs>();
internal BindingSource bindingSource;

private void button1_Click(object sender, EventArgs e)
{
    bindingSource = new BindingSource();

    InputData.AddRange(new [] { 
        new Inputs() { Id = 5476, Name = "Smith" },
        new Inputs() { Id = 5477, Name = "Marlin" }
    });

    bindingSource.DataSource = InputData;

    Binding tboxBind = new Binding("Text", bindingSource, "Id", false, DataSourceUpdateMode.OnPropertyChanged);

    tboxBind.Parse += (pObj, pEvt) =>
    {
        if (!int.TryParse(pEvt.Value.ToString(), out int value))
            bindingSource.ResetCurrentItem();
    };
    textBox1.DataBindings.Add(tboxBind);
    dataGridView1.DataSource = bindingSource;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...