Textbox подключен к базе данных, но без DataGridView я не могу выбрать нужную мне запись
У меня есть две формы. На одной из них находится таблица со всеми записями и несколько кнопок (Добавить, Редактировать, Удалить). Кнопка "Редактировать" переносит на вторую форму, на которой находятся Textboxs привязанные к таблице на первой форме. Мне нужно сделать так, чтобы выбирая какую-то строку в DataGridView на первой форме, я мог редактировать её значения на второй, а после сохранить изменения, и обновить таблицу.
Ответы (1 шт):
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