Textbox подключен к базе данных, но без DataGridView я не могу выбрать нужную мне запись

У меня есть две формы. На одной из них находится таблица со всеми записями и несколько кнопок (Добавить, Редактировать, Удалить). Кнопка "Редактировать" переносит на вторую форму, на которой находятся Textboxs привязанные к таблице на первой форме. Мне нужно сделать так, чтобы выбирая какую-то строку в DataGridView на первой форме, я мог редактировать её значения на второй, а после сохранить изменения, и обновить таблицу.


Ответы (1 шт):

Автор решения: alexpanarin
    namespace WinFormsDraw.Bindings
    {
        public interface IModel
        {
            int? Id { get; }
        }
    }
    namespace WinFormsDraw.Bindings
    {
        public class DataModel
            : IModel
        {
            [Key]
            [Required]
            public int? Id { get; protected set ; }
            [Required]
            [StringLength(50, ErrorMessage = "Значение не должно превышать 50 символов.")]
            public string? Name { get; set ; } 
            public string? Description { get; set ; }
            [DataType(DataType.Url)]
            public string? Url { get; set ; }
        }
    }
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    namespace WinFormsDraw.Bindings
    {
        public class ModelWrapper <TModel>
            : INotifyPropertyChanged
            where TModel : class, IModel
        {
            PropertyDescriptorCollection _properties;
            public ModelWrapper(TModel model)
            {
                Model = model;
                _properties = TypeDescriptor.GetProperties(Model);
            }
            protected TModel Model { get; private set; }
            public event PropertyChangedEventHandler? PropertyChanged;

            protected void RaisePropertyChanged([CallerMemberName]string? propertyName = null)
            {
                if (propertyName == null) return;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }

            protected TValue? GetValue<TValue>([CallerMemberName] string? propertyName = null)
            {
                if (propertyName == null) return default;

                return (TValue?)_properties[propertyName]?.GetValue(Model);
            }

            protected void SetValue<TValue>(TValue value, [CallerMemberName] string? propertyName = null )
            {
                if (propertyName == null) return;
                _properties[propertyName]?.SetValue(Model, value);
                RaisePropertyChanged();
            }
        }
    }
     using System.ComponentModel;

    namespace WinFormsDraw.Bindings
    {
        public class DataModelWrapper
            : ModelWrapper<DataModel>
        {
            public DataModelWrapper(DataModel model)
                : base(model)
            {
            }

            [Browsable(false)]
            public int? Id { get => GetValue<int?>(); set => SetValue(value); }

            [Description("Наименование")]
            [DisplayName("Наименование")]
            public string? Name { get => GetValue<string?>(); set => SetValue(value); }
            [Description("Описание")]
            [DisplayName("Описание")]
            public string? Description { get => GetValue<string?>(); set => SetValue(value); }
            [Description("Ссылка")]
            [DisplayName("Ссылка")]
            public string? Url { get => GetValue<string?>(); set => SetValue(value); }
        }
    }    
    namespace WinFormsDraw.Bindings
    {
        public partial class BindingForm : Form
        {
            public BindingForm()
            {
                InitializeComponent();

                bindingSource.DataSource = new DataModelWrapper[]
                {
                    new DataModelWrapper(new DataModel { Name = "Один", Description="Описание Один", Url="Ссылка Один"}),
                    new DataModelWrapper(new DataModel { Name = "Два", Description="Описание Два", Url="Ссылка Два"}),
                    new DataModelWrapper(new DataModel { Name = "Три", Description="Описание Три", Url="Ссылка Три"}),
                };
            }
        }
    }

    partial class BindingForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
            dataGridView1 = new DataGridView();
            bindingSource = new BindingSource(components);
            panel = new Panel();
            textThree = new TextBox();
            textTwo = new TextBox();
            textOne = new TextBox();
            nameDataGridViewTextBoxColumn = new DataGridViewTextBoxColumn();
            descriptionDataGridViewTextBoxColumn = new DataGridViewTextBoxColumn();
            urlDataGridViewTextBoxColumn = new DataGridViewTextBoxColumn();
            ((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit();
            ((System.ComponentModel.ISupportInitialize)bindingSource).BeginInit();
            panel.SuspendLayout();
            SuspendLayout();
            // 
            // dataGridView1
            // 
            dataGridView1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            dataGridView1.AutoGenerateColumns = false;
            dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            dataGridView1.Columns.AddRange(new DataGridViewColumn[] { nameDataGridViewTextBoxColumn, descriptionDataGridViewTextBoxColumn, urlDataGridViewTextBoxColumn });
            dataGridView1.DataSource = bindingSource;
            dataGridView1.Location = new Point(10, 8);
            dataGridView1.Name = "dataGridView1";
            dataGridView1.Size = new Size(568, 320);
            dataGridView1.TabIndex = 0;
            // 
            // bindingSource
            // 
            bindingSource.DataSource = typeof(DataModelWrapper);
            // 
            // panel
            // 
            panel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            panel.Controls.Add(textThree);
            panel.Controls.Add(textTwo);
            panel.Controls.Add(textOne);
            panel.Location = new Point(10, 350);
            panel.Name = "panel";
            panel.Size = new Size(568, 35);
            panel.TabIndex = 1;
            // 
            // textThree
            // 
            textThree.DataBindings.Add(new Binding("DataContext", bindingSource, "Url", true));
            textThree.DataBindings.Add(new Binding("Text", bindingSource, "Url", true));
            textThree.Location = new Point(373, 6);
            textThree.Name = "textThree";
            textThree.Size = new Size(179, 23);
            textThree.TabIndex = 2;
            // 
            // textTwo
            // 
            textTwo.DataBindings.Add(new Binding("DataContext", bindingSource, "Description", true));
            textTwo.DataBindings.Add(new Binding("Text", bindingSource, "Description", true));
            textTwo.Location = new Point(188, 6);
            textTwo.Name = "textTwo";
            textTwo.Size = new Size(179, 23);
            textTwo.TabIndex = 1;
            // 
            // textOne
            // 
            textOne.DataBindings.Add(new Binding("Text", bindingSource, "Name", true));
            textOne.DataBindings.Add(new Binding("DataContext", bindingSource, "Name", true));
            textOne.Location = new Point(3, 6);
            textOne.Name = "textOne";
            textOne.Size = new Size(179, 23);
            textOne.TabIndex = 0;
            // 
            // nameDataGridViewTextBoxColumn
            // 
            nameDataGridViewTextBoxColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
            nameDataGridViewTextBoxColumn.DataPropertyName = "Name";
            nameDataGridViewTextBoxColumn.HeaderText = "Наименование";
            nameDataGridViewTextBoxColumn.Name = "nameDataGridViewTextBoxColumn";
            nameDataGridViewTextBoxColumn.Width = 115;
            // 
            // descriptionDataGridViewTextBoxColumn
            // 
            descriptionDataGridViewTextBoxColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            descriptionDataGridViewTextBoxColumn.DataPropertyName = "Description";
            descriptionDataGridViewTextBoxColumn.HeaderText = "Описание";
            descriptionDataGridViewTextBoxColumn.Name = "descriptionDataGridViewTextBoxColumn";
            descriptionDataGridViewTextBoxColumn.Width = 200;
            // 
            // urlDataGridViewTextBoxColumn
            // 
            urlDataGridViewTextBoxColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            urlDataGridViewTextBoxColumn.DataPropertyName = "Url";
            urlDataGridViewTextBoxColumn.HeaderText = "Ссылка";
            urlDataGridViewTextBoxColumn.Name = "urlDataGridViewTextBoxColumn";
            // 
            // BindingForm
            // 
            AutoScaleDimensions = new SizeF(7F, 15F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(590, 450);
            Controls.Add(panel);
            Controls.Add(dataGridView1);
            Name = "BindingForm";
            Text = "BindingForm";
            ((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit();
            ((System.ComponentModel.ISupportInitialize)bindingSource).EndInit();
            panel.ResumeLayout(false);
            panel.PerformLayout();
            ResumeLayout(false);
        }

        #endregion

        private DataGridView dataGridView1;
        private BindingSource bindingSource;
        private Panel panel;
        private TextBox textThree;
        private TextBox textTwo;
        private TextBox textOne;
        private DataGridViewTextBoxColumn nameDataGridViewTextBoxColumn;
        private DataGridViewTextBoxColumn descriptionDataGridViewTextBoxColumn;
        private DataGridViewTextBoxColumn urlDataGridViewTextBoxColumn;
    }
}

Как это все работает. На форму накидываем DataGridView и компонент BindingSource. Создаем модель данных. Можно посмотреть как это делается в комментарии, который вам дали, можно как у меня (у меня разделены модель данных и DTO). Атрибуты над свойствами модели определяют как отображать (или не отображать :) их в DataGridView. КОМПИЛИРУЕМ ПРОЕКТ. В дизайн тайм в свойство bindingSource.DataSource визардом (в выпадающем списке внизу -> Add New Object Data Source) привязываем тип данных с которым будете работать (у мня DataModelWrapper). В свойство dataGridView.DataSource присваиваете объект bindingSource. КОМПИЛИРУЕМ ПРОЕКТ. Открываем в дизайнере вашу форму, и наблюдаем что появились заголовки колонок в соответствии с вашей моделью. Далее я накидал три TextBox и в их свойство DataBindings.DataContext связал через выпадающий список соответственно свойства bindingSource Name, Description, Url. В конструкторе BindingForm создаем источник данных (массив DataModelWrapper[]) и присваеваем его свойству bindingSource.DataSource. Запускаем проект. При перемещении по гриду свойства в текстбокс будут менять соответственно. При редактировании свойства в текстбокс новое значение отображается в гриде. ВНИМАНИЕ значение будет меняться в гриде при изменении фокуса на другой контрол.

Рекомендую изучить, что такое Binding (для WindowsForms). И посмотреть описание класса BindingSource

→ Ссылка