Толик Панков
hex_laden
............ .................. ................
Толик Панков [userpic]
C#, WindowsForms. Автоматическая выгрузка и загрузка содержимого контролов на форме.

Решил побороть еще одно узкое место в коде, которое приводит к невероятному количеству ручного кодинга, а именно - загрузка данных из записи DataSet или произвольного объекта в форму, для изменения/ввода данных пользователем, а потом обратная выгрузка.

Вообще, долго думал и гуглил, как сей неприятный процесс автоматизировать, но почему-то везде предлагали либо встроенные, либо сторонние генераторы кода, т.е. ответ был "генерируй!". Но меня такой ответ не устроил, неужто, никак нельзя все это более-менее автоматизировать, не прибегая к внешним инструментам.

Оказывается, можно. Все инструменты для этого есть - есть System.Reflection, через инструменты данного пространства имен можно получать имена свойств или полей нужного класса, а также тип данных, и есть методы для поиска нужных контролов на форме, чтобы загрузить или сохранить данные в/из объекта.

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

Опять же, тут будет краткое рассуждение, а пример кода в конце.

Основные компоненты


Основные компоненты это:
- текстовые поля, куда можно ввести либо строку, либо число (фильтрацию ввода оставим форме)
- checkbox'ы, хранящие булево значение
- radiobutton'ы/переключатели - ограниченный выбор из определенного набора вариантов.

От этой печки танцевать и будем, если понадобится что-то еще - это будет уже проще свести к этим трем типам, или, немного изменив код, добавить конкретный случай в класс-прослойку.

Как хранить набор вариантов


Тут уже придумали все за нас, есть прекрасный тип Enum, который, собственно, для этого и предназначен. Например, нам надо будет хранить тип соединения с сетью. Можно сделать вот такое перечисление:

public enum NetConnectionType
{
    NoProxy = 0,
    SystemProxy = 1,
    ManualProxy = 2
}


Соглашение об именах

Это единственный наглый момент во всем примере - контролы придется называть не абы как, а по правилам, впрочем, правила всегда можно переопределить, и сделать удобные вам. Я делал удобно для себя.
Для TextBox'ов и CheckBox'ов правила такие: сначала идет префикс txt или chk, далее - название поля в записи таблицы DataSet или название свойства объекта, например chkAutorun или txtUserName. В классе, соответственно, должны быть поля bool Autorun или string UserName.

Для радиокнопок (переключателей) имя формируется по следующему принципу: префикс rb+НазваниеСвойства+ЗначениеВEnum, т.е., например, радиокнопка, указывающая на прямое соединение, будет называться rbConnectionNoProxy

Думаете, сложно и длинно? Ну, может быть, только сталкиваешься с этим потом один раз, когда моделируешь форму.

Разные вспомогательные мелочи


Получение списка радиокнопок и поиск контрола на форме Копия

Получение значения Enum из состояния RadioButton:

private string GetEnumValFromRb(string PropName)
{
    string EnumVal = string.Empty;
    string rbName = "rb"+PropName;            
    
    foreach (RadioButton rb in RadioButtons)
    {                
        if (rb.Checked)
        {
            if (rb.Name.StartsWith(rbName))
            {
                EnumVal = rb.Name.Substring(rbName.Length);
            }
        }
    }

    return EnumVal;
}


Весь код примера


На GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2018/06/29/c-windowsforms-avtomaticheskaya-vygruzka-i-zagruzka-soderzhimogo-kontrolov-na-forme-v-obekt-ili-zapis-dataset/

Tags: ,
Comments

Охуенчик же!

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

Пасиб! :)

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

Не въезжаю, как тут можно обойтись без кодогенерации. Я имею в виду, если правильно понимаю, вы сохраняете или грузите состояние WinForms UI Input в датасет. Это предполагает наличие датасета с нужными полями. Но ведь его никак, кроем генерацией кода, не создать?

С чего бы Датасет автоматом не создать-то?
Я ж уже показывал. http://lj.rossia.org/users/hex_laden/393218.html

С Датасетом, ИМХО, даже проще и нагляднее!

а, Вы правы конечно, это object не создать так