Перенос данных между формами

79
22 марта 2022, 07:30

Есть две формы, на одной отображаются данные в таблице на другой они добавляются. Надо что бы после нажатия сохранить на второй форме, внесенные данные отображались в таблице на первой форме. Можно конечно добавить на первую таблицу таймер который будет в случае изменений в таблице ее перестраивать. Но может вы подскажите более правильное решение.

Answer 1

Создадим класс модели данных с поддержкой IDataErrorInfo для работы ErrorProvider в форме

public class Person : IDataErrorInfo
{
    public int OrderNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    #region Реализация IDataErrorInfo
    public string _Error;
    public string Error => _Error;
    public string this[string columnName] => CheckProperties(columnName);
    /// <summary>
    /// Проверка значений свойств на валидность
    /// </summary>
    /// <param name="columnName">имя проверяемого свойства</param>
    /// <returns>строка с описанием ошибки</returns>
    private string CheckProperties(string columnName)
    {
        if (columnName.Equals(nameof(FirstName)) && String.IsNullOrEmpty(FirstName))
        {
            _Error = "Укажите имя";
            return _Error;
        }
        if (columnName.Equals(nameof(FirstName)) && FirstName?.Trim().Length < 2)
        {
            _Error = "Имя не может быть короче двух символов";
            return _Error;
        }
        if (columnName.Equals(nameof(LastName)) && String.IsNullOrEmpty(LastName))
        {
            _Error = "Укажите фамилию";
            return _Error;
        }
        if (columnName.Equals(nameof(LastName)) && LastName?.Trim().Length < 2)
        {
            _Error = "Фамилия не может быть короче двух символов";
            return _Error;
        }
        _Error = String.Empty;
        return _Error;
    }
    #endregion
    /// <summary>
    /// Валиден ли данный чел.
    /// </summary>
    /// <returns></returns>
    public bool IsValid()
    {
        var errorFN = this["FirstName"];
        var errorLN = this["LastName"];
        _Error = errorFN + " " + errorLN;
        return String.IsNullOrWhiteSpace(Error);
    }
}

Форма ввода данных, в ней мы объявляем событие DataEntered, с помощью которого будем оповещать главную форму о том, что данные готовы, и их можно забрать

public partial class FormInput : Form
{
    //редактируемая модель
    private readonly Person _person;
    //событие готовности данных для чтения FormMain
    public EventHandler DataEntered;
    public FormInput()
    {
        InitializeComponent();
        _person = new Person();
        _buttonSave.Click += ButtonSave_Click;
        this.Load += FormInput_Load;
    }
    private void FormInput_Load(object sender, EventArgs e)
    {
        //привязки свойств модели к текстбоксам
        _textBoxFirstName.DataBindings.Add("Text", _person, nameof(_person.FirstName),
            true, DataSourceUpdateMode.OnPropertyChanged);
        _textBoxLastName.DataBindings.Add("Text", _person, nameof(_person.LastName),
            true, DataSourceUpdateMode.OnPropertyChanged);
        //привязка ErrorProvider для отображения ошибок ввода
        _errorProvider.DataSource = _person;
    }
    private void ButtonSave_Click(object sender, EventArgs e)
    {
        //проверяем введенные данные на валидность
        if (!_person.IsValid())
        {
            var message = $"Не все данные введены верно!\n{_person.Error}";
            var caption = "Предупреждение";
            MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }
        //данные валидные значит вызываем событие для оповещения FormMain
        DataEntered?.Invoke(this, EventArgs.Empty);
    }
    /// <summary>
    /// Получение чела для вставки в DGV
    /// </summary>
    /// <param name="number">назначаемый порядковый номер</param>
    /// <returns>экземпляр Person</returns>
    public Person GetPerson(int number)
    {
        //создаем нового чела для передачи
        var result = new Person
        {
            OrderNumber = number,
            FirstName = new string(_person.FirstName.Trim().ToCharArray()),
            LastName = new string(_person.LastName.Trim().ToCharArray()),
        };
        //поля ввода очищаем
        _textBoxFirstName.Text = String.Empty;
        _textBoxLastName.Text = String.Empty;
        _textBoxFirstName.Focus();
        return result;
    }
}

Главная форма, с формой ввода работаем через событие

public partial class FormMain : Form
{
    //ссылка на форму ввода данных
    private FormInput _inputForm;
    //источник данных для DGV
    private readonly BindingSource _bsPeople;
    public FormMain()
    {
        InitializeComponent();
        _bsPeople = new BindingSource();
        _buttonOpenInput.Click += ButtonOpenInput_Click;
        this.Load += FormMain_Load;
    }
    private void FormMain_Load(object sender, EventArgs e)
    {
        _bsPeople.DataSource = typeof(List<Person>);
        //привязка к данным DGV
        _dataGridView.AutoGenerateColumns = false;
        _dataGridView.DataSource = _bsPeople;
        //привязка свойств модели к колонкам DGV
        _columnOrderNumber.DataPropertyName = nameof(Person.OrderNumber);
        _columnLastName.DataPropertyName = nameof(Person.LastName);
        _columnFirstName.DataPropertyName = nameof(Person.FirstName);
    }
    /// <summary>
    /// Кнопка Добавить
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ButtonOpenInput_Click(object sender, EventArgs e)
    {
        if (_inputForm != null)
            return;
        _inputForm = new FormInput();
        _inputForm.Owner = this;
        //подписываемся на событие готовности данных
        _inputForm.DataEntered += FormInput_DataEntered;
        _inputForm.FormClosed += InputForm_FormClosed;
        //отображаем форму
        _inputForm.Show();
    }
    /// <summary>
    /// Обработчик события готовности данных в FormInput
    /// Здесь мы извлекаем данные и вносим их в DGV
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void FormInput_DataEntered(object sender, EventArgs e)
    {
        //вычисляем порядковый номер для след.чела
        int number = _bsPeople.Count + 1;
        //добавляем в DGV нового чела
        _bsPeople.Add(_inputForm.GetPerson(number));
    }
    /// <summary>
    /// Обработчик события закрытия формы ввода
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void InputForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        _inputForm = null;
    }
}

Пример целиком здесь.

READ ALSO
Если бы ASP.NET Core был одно-поточен

Если бы ASP.NET Core был одно-поточен

Согласно моему познанию ASPNET Core и если сильно не углубляться в детали, то на сегодняшний день обработка HTTP-запросов на одноядерном процессоре...

170
Обобщённое приведение IQueryable к IOrderedQueryable

Обобщённое приведение IQueryable к IOrderedQueryable

У меня есть generic метод преобразующий IQueryable<T> и возвращающий IOrderedQuerable<T> при помощи Linq-to-Entities

70
Как добавить ReactJS к проекту AspNet?

Как добавить ReactJS к проекту AspNet?

Пытаюсь как тут добавить ReactJS к проекту, но при добавлении этой строки:

107
Как ставить Awake&#39;и в очередь

Как ставить Awake'и в очередь

У меня есть несколько скриптов, в одном выполняется в Awake парсинг xml, и значения заносятся в Dictionary, а в других выполняется получение значения...

117