Создание программы - ООП модель, MVP

Storm23

, А можно пример? Вообще-то я не совсем понимаю, зачем такие сложности?

Неудачный пример немного, но я понял. Только если вот так, например, что в первом вопросе респондент отвечает про пиво, то следующий вопрос, который содержит Condition вопроса и варианта уже не будет содержать вариантов с пивом - тут можно создать два вопроса, каждый условно будет ссылаться на тех, кто пьёт пиво и на тех, кто не пьёт и вести параллельно две ветки вариантов уже для каждой категории. Но я понял, что так экономится количество вопросов и что на дальнейших вопросах можно делать пересечения с выбором.

Посмотрите, пожалуйста, как я поправил и сравните.

Да, про радиобаттоны забыл. Я сначала хотел определять верный вариант, потом до меня дошло, что это же просто анкета. Да, надо убрать. А про Build - щас гляну.

Добавлено через 8 минут

Storm23

, там ещё момент какой-то мутный в дизайнере - сам UserControl с вопросом начинает расширяться, если начинать добавлять альтернативу. Там, в дизайнере, якоря стоят то на правую сторону, то на левую - изменяешь размер QuestPanel и внутри контролы ползут друг на друга.

Добавлено через 16 минут

про комбобоксы я объяснил, что можно сделать в них вывод имеющихся вопросов - так просто проще для пользователя определять зависимые вопросы от добавленных вариантов - я не успел.

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

Да, я его изменил. Поясняю - я переработал некоторые моменты.

Код в Build, который делал вот это

Кликните здесь для просмотра всего текста

C#Выделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

private void Build()
        {
            //очищаем центральную панель
            //pnMain.Controls.Clear();
 
            //создаем контролы для каждого вопроса
            //foreach (var quest in _questionnaire)
            //{
                
 
                
            //}
 
            //обновляем интерфейс
            UpdateInterface();
        }

Я поменял на вот это:

Подписка на события

Кликните здесь для просмотра всего текста

C#Выделить код

| | |
| --- | --- |
| 1 | pn.QuestionnaireListChanged += ProcessQuestionListAction; |

Тело делегата тоже изменил

Кликните здесь для просмотра всего текста

C#Выделить код

1
2
3
4
5

private void ProcessQuestionListAction(string questionPanelKey, UserPanelActionType actionType)
        {
            FlowPanelActionHelper.ProcessElements(questionPanelKey, actionType);
            _changed = true;//выставлем флажок изменения
        }

Так как у вас повторяются действия по двум моментам с FlowPanel я решился добавить общий обработчк на оба случая.

Кликните здесь для просмотра всего текста

C#Выделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

public class FlowPanelActionHelper
    {
        private FlowLayoutPanel FlowLayoutPanel { get; }
 
        public FlowPanelActionHelper(FlowLayoutPanel flowLayoutPanel)
        {
            FlowLayoutPanel = flowLayoutPanel;
        }
        
        /// <summary>
        /// Управление пользовательскими элементами управления внутри FlowLayoutControl
        /// </summary>
        /// <param name="elementKey">Ключ элемента управления</param>
        /// <param name="actionType">Тип действия над элементом управления</param>
        public void ProcessElements(string elementKey, UserPanelActionType actionType)
        {
 
            switch (actionType)
            {
                case UserPanelActionType.Remove:
                    FlowLayoutPanel.Controls.RemoveByKey(elementKey);
                    break;
                case UserPanelActionType.MoveUp:
                case UserPanelActionType.MoveDown:
                    //создаем хелпер отрисовки, останавливаем отрисовку
                    var helper = new ControlHelper(FlowLayoutPanel);
                    var movingAlt = FlowLayoutPanel.Controls.Find(elementKey, false).First();
                    if (movingAlt == null) break;
 
                    var controlIndex = FlowLayoutPanel.Controls.IndexOfKey(elementKey);
 
                    /ограничение на циклическую перестановку пользовательских элементов управления внутри FlowLayoutControl/
                    if (controlIndex == 0 && actionType == UserPanelActionType.MoveUp) break;
 
                    FlowLayoutPanel.Controls.SetChildIndex(movingAlt, controlIndex + (int)actionType);
                    helper.ResumeDrawing();
                    break;
            }
            
        }
    }

Мне эта реализация нравится намного больше вашей, поэтому я позволил себе такие выходки. Да и используется это намного удобнее, чем постоянная перерисовка элементов управления с нуля. Да и сложности в самом коде я не встретил при реализации - сам FlowLayoutPanel диктовал мне путь))) Я ещё хотел сделать вообще наследуемые UserControl от этого класса, чтобы иметь внутри формы свои методы обработки, но потом осёкся, так как нужно было делать статичную передачу FlowLayoutPanel в базовый класс, для этого бы мне в самом Designer проставить везде static у FlowLayoutPanel - что является бредом. Да и не унаследуешь сразу и форму и UserControl от UserControl....