Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3

[РЕФАКТ] Control.Controls сделать внутри Swap

31.05.2022, 22:38. Показов 1859. Ответов 15

Студворк — интернет-сервис помощи студентам
Задача проще не куда:
нужно сделать свап внутри Control.Controls,

но не тут то было...

как оказалось, Control.Controls не позволяет присваивать значения(по всему под капотом там указатели) контролов
и отсюда мои "мучения".

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

поэтому получился вот такой страшненький кот:
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
        public static void Swap(ref Control[] m, int i, int j)
        {   var tmp = m[i];
                  m[i] = m[j];
                  m[j] = tmp;
        }
 
        public static void SwapL(ref Control a, ref Control b)
        {   var tmp = a.Left;
                a.Left = b.Left;
                b.Left = tmp  ;
        }
 
        public static void MoveControlBack(Control a)
        {
            Panel p = (Panel)a.Parent;
            Control[] m = p.Controls.Find(p.Name, true);
 
            var i = 0;
 
            foreach (var o in m)
            {
                if (o == a) break;
                ++i;
            }
 
            if (0 != i)
            {
                int j = i - 1;
 
                Swap(ref m, i, j);
                SwapL(ref m[i], ref m[j]);
 
                foreach (var o in m) p.Controls.Remove(o);
                foreach (var o in m) p.Controls.Add   (o);
            }
        }
да, весьма страшненький, чтобы сделать свап двух контролов,
мне пришлось ТРИ раза пройтись по Control.Controls

ещё неприятный артифакт - вздрагивание(или моргание) всех котролов(там у мя PictureBox) при клике для свапа.

А как, всё-таки, сделать правильно?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.05.2022, 22:38
Ответы с готовыми решениями:

foreach(Control x in this.Controls)
foreach(Control x in this.Controls) как это работает?

How programatically disable all controls within frame without actually specifying each control name?
Hello! I have Control array of 5 frames on the form. Each frame containes different controls. When I disable each frame, how...

Использование std::swap() вместо friend swap() при реализации Copy&Swap в современном С++
Добрый день! При реализации Copy&Swap традиционно для класса создается дружественная функция swap(), которая используется в перегруженном...

15
2394 / 1923 / 763
Регистрация: 27.07.2012
Сообщений: 5,567
31.05.2022, 23:06
Цитата Сообщение от XLAT Посмотреть сообщение
Задача проще не куда:
нужно сделать свап внутри Control.Controls
Так смысл в чём? Поменять их местами на форме или поменять местами в коллекции Controls? Просто, мне казалось, что их очерёдность в коллекции вообще значения не имеет.
1
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
31.05.2022, 23:18  [ТС]
Цитата Сообщение от John Prick Посмотреть сообщение
Так смысл в чём? Поменять их местами на форме или поменять местами в коллекции Controls? Просто, мне казалось, что их очерёдность в коллекции вообще значения не имеет.
ну, да в какой то степени это академическая задача на знание чаво могёт Forms...

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

но а если контролы разнотипные?

Цитата Сообщение от John Prick Посмотреть сообщение
Так смысл в чём?
делаю простую библу БЕЗ привязки к конкретной задаче,
что то типа аля STL для некого множества задач схожего типа...
0
2394 / 1923 / 763
Регистрация: 27.07.2012
Сообщений: 5,567
31.05.2022, 23:28
Цитата Сообщение от XLAT Посмотреть сообщение
но а если контролы разнотипные?
Ну, видимо, на уровне родительского контрола большего о них знать и не требуется. Положение, размеры да и всё.
1
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 08:05  [ТС]
Цитата Сообщение от XLAT Посмотреть сообщение
C#
18
19
20
21
22
23
            var i = 0;
            foreach (var o in m)
            {
                if (o == a) break;
                ++i;
            }
вчера, как баран смотрел в всплывающие подсказки и не мог увидеть, что:
C#
18
            var i = p.Controls.IndexOf(a);
хоть и мелочь, но уже приятно ...

Добавлено через 11 минуту
Пытаюсь красиво засвапить свойства контролов:
C#
1
2
3
4
5
6
7
8
9
        public static void Swap<T>(ref T a, ref T b)
        {   T t = b;
              b = a;
              a = t;
        }
 
...
 
        Swap(ref m[i].Left, ref m[j].Left); // m[i] это контрол в Contol.Controls
Ошибка компиляции: Свойство m[i].Left не может быть ссылочным ...

Формокодеры, как вы с этим живёте?
0
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 10:21  [ТС]
Итого: под задачу всё свелось к такому коду:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        public static void SwapImg(ref Panel p, int i, int j)
        {
            PictureBox a = (PictureBox)p.Controls[i];
            PictureBox b = (PictureBox)p.Controls[j];
            {
                var tmp = a.Image;
                a.Image = b.Image;
                b.Image = tmp;
            }
            {
                var tmp = a.Tag;
                a.Tag = b.Tag;
                b.Tag = tmp;
            }
        }
 
        public static void MoveControlBack(Control a)
        {
            Panel p = (Panel)a.Parent;
            var i = p.Controls.IndexOf(a);
            if (0 != i) SwapImg(ref p, i, i - 1);
        }
кодо-универсальность обобщённым кодом пала жертвой храброй ...

но зато перестало моргать, а это дорого стоит)

этот кусочек задачи выглядит так:
0
 Аватар для ViterAlex
8952 / 4864 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
01.06.2022, 10:32
Лучший ответ Сообщение было отмечено XLAT как решение

Решение

XLAT, методы RemoveAt и Insert ты не рассматривал?
1
1168 / 886 / 517
Регистрация: 09.04.2014
Сообщений: 2,101
01.06.2022, 10:37
Лучший ответ Сообщение было отмечено XLAT как решение

Решение

а чтобы не моргало - SuspendLayout()/ResumeLayout()
1
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 11:50  [ТС]
Цитата Сообщение от ViterAlex Посмотреть сообщение
методы RemoveAt и Insert ты не рассматривал?
так, рассмотрел.
для Control.Control метод RemoveAt есть и работает,
а вот Insert для IList который реализует тот же Control.Control отсутствует.

Цитата Сообщение от nedel Посмотреть сообщение
SuspendLayout()/ResumeLayout()
да, я уже понял что вызов события мыши асинхронный, что естественно,
поэтому надо бы как то запретить перерисовку на время переупорядочивания контролов.
почитал доку, как SuspendLayout()/ResumeLayout()работает
всё ясно и понятно)
добавил в обработку клика на всякий случай))
0
 Аватар для ViterAlex
8952 / 4864 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
01.06.2022, 12:23
А это что? iList.Insert
0
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 12:57  [ТС]
Цитата Сообщение от ViterAlex Посмотреть сообщение
А это что? iList.Insert

т.е. выше я хотел написать,
что iList не реализован или реализован не полностью для Control.Controls


Итого текущая, имхо, лучшая версия:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        public static void SwapPosLeft(ref Control a, Control b)
        {
            var tmp = a.Left;
            a.Left = b.Left;
            b.Left = tmp;
        }
 
        public static void MoveControlBack(Control a)
        {
            Panel p = (Panel)a.Parent;
            var i = p.Controls.IndexOf(a);
            if (i > 0)
            {
                p.Controls.SetChildIndex(a, i - 1);
                SwapPosLeft(ref a, p.Controls[i]);
            }
        }
PS:
считаю, что рефакторинг удался.
Спасибо за помощь!
0
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 13:25  [ТС]
Цитата Сообщение от XLAT Посмотреть сообщение
C#
10
    Panel p = (Panel)a.Parent;
мда, разумеется так:
C#
1
    Control p = a.Parent;
вот теперь по настоящему абстрактно.
что касаемо свойства Left, то предположу, что оно есть у всех контролов,
в любом случае, в отображаемых, для которых, собсно, и предназначается этот метод.

а ваще, конешъ, туда лямбду о позиционировании надо бы передавать))
0
 Аватар для ViterAlex
8952 / 4864 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
01.06.2022, 13:39
Цитата Сообщение от XLAT Посмотреть сообщение
что iList не реализован или реализован не полностью для Control.Controls
Там надо кастовать к интерфейсу.
0
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 15:42  [ТС]
Цитата Сообщение от ViterAlex Посмотреть сообщение
Там надо кастовать к интерфейсу.
C#
1
IList<Control> W = (IList<Control>)p.Controls;
в рантайме:
Code
1
2
3
ERROR: System.InvalidCastException: 
Не удалось привести тип объекта "ControlCollection" к типу
"System.Collections.Generic.IList`1[System.Windows.Forms.Control]".
Добавлено через 2 минуты
insert(i, a)
Code
1
2
p.Controls.Add(a);
p.Controls.SetChildIndex(a, i);
0
 Аватар для ViterAlex
8952 / 4864 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
01.06.2022, 15:52
XLAT, там не дженерик
Изображения
 
0
Just Do It!
 Аватар для XLAT
4211 / 2670 / 655
Регистрация: 23.09.2014
Сообщений: 9,083
Записей в блоге: 3
01.06.2022, 16:29  [ТС]
Цитата Сообщение от ViterAlex Посмотреть сообщение
там не дженерик
C#
1
2
                System.Collections.IList w = (System.Collections.IList)p.Controls;
                w.Insert(0, a);
в рантайме на w.Insert(0, a);
Code
1
2
3
4
ERROR: System.NotSupportedException: 
Указанный метод не поддерживается.
в System.Windows.Forms
.Layout.ArrangedElementCollection.System.Collections.IList.Insert(Int32 index, Object value)
уже ближе ...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.06.2022, 16:29
Помогаю со студенческими работами здесь

Control array: как динамически создавать controls ?
Что ни пробовал, новые элементы в control array (vb6) создаются только в режиме design. Пробовал ReDim для созданного в дизайне control...

Вызов Controls из .dll Library (from Custom SelfMade Control)
Здравствуйте, скажите, пожалуйста, возможно ли осуществить подобное: Существует созданная Library, которая является панелью с двумя...

Control внутри Popup
Доброго времени суток, уважаемые форумчане. Подскажите. Бьюсь над вопросом: можно-ли создать внутри Popup menu объект типа control...

Методы Controls.Clear и Controls.Remove активируют форму. Можно ли это запретить?
При вызове методов Control.ControlCollection.Clear() и Control.ControlCollection.Remove(Control control) при динамическом обновлении...

Ошибка: Window does not contain a definition for 'Controls' and no extension method 'Controls'
Решил заняться c#, но что-то не могу разобраться. имеется некоторое количество textBox'ов (textBox1, textBox2...). Через цикл хотел...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru