ChewsHumans Ответов: 4

Почему стыковка Windows Forms не работает должным образом, когда вложенность глубока?


Привет. Надеюсь, кто-нибудь сможет мне помочь. Я уже несколько недель ломаю голову над этим вопросом и, кажется, ничего не могу сделать.

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

О, он не просто не может изменить размер. Это было бы просто. Нет, его границы меняются, и в некоторых (но не во всех) случаях он перекрашивает себя должным образом, но текст продолжает обертываться на том же месте, даже несмотря на то, что размер элемента управления изменился.

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

Я удалил весь код. Проблема оставалась.

Единственный оставшийся код-это графический код, который Visual Studio помещает за кулисы, когда вы добавляете элементы управления в поверхность дизайна, и небольшое количество дополнительного кода для окраски различных элементов управления, чтобы я мог видеть, что происходит.

Теперь я не могу очень хорошо вставить сюда код конструктора Windows Forms-он довольно многословен, как обычно бывает с таким кодом. Кроме того, есть полдюжины различных классов (все почти пустые). Итак, я загрузил исходный код и исполняемый файл отдельно в MegaUpload:

Источник: http://www.megaupload.com/?d=LDP09KRY[^]
Выполнимый: http://www.megaupload.com/?d=P7QKDMJJ[^]

Если вы не доверяете исполняемым файлам, просто загрузите исходный код. Он состоит из проекта и решения VS2010, а также полудюжины пользовательских элементов управления, которые не содержит кода.

Чтобы воспроизвести задачу, запустите программу и наблюдайте за тремя наборами концентрических квадратов. Каждый из них представляет собой панель, tablelayoutpanel или usercontrol. В центре каждого находится текстовое поле. Сделайте окно шире и обратите внимание, что текст в верхнем текстовом поле не переносится повторно, чтобы соответствовать новой ширине текстового поля.

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

Интересно отметить, что если я просто вложу элементы управления вместо использования (бескодовых) пользовательских элементов управления; или если я использую однострочное текстовое поле или, скажем, кнопку, проблема исчезнет. Насколько я помню, проблема на самом деле не в этом ограниченный к многострочным текстовым полям, но в данном случае я смог воспроизвести его только с ними.

Я был бы очень признателен Вам за помощь, ребята. Ничто из того, что я пытаюсь сделать, не помогает. Я пробовал добавлять вызовы PerformLayout и тому подобное, но они ничего не делают. (К сожалению, исходный код Microsoft для кода макета содержит комментарии примерно следующего содержания:"этот бит не должен быть нужен, Но если я его выну, все сломается". Я думал, что Microsoft должна была понимать эта штука?)

Пожалуйста, не предлагайте глупые вещи вроде "не используйте стыковку" или "не вкладывайте свои элементы управления так глубоко" - они бесполезны. Причина в том, что стыковка-это официальный метод организации элементов управления в .NET; и даже если бы я чувствовал себя в состоянии уменьшить уровень вложенности (чего мне все равно не следовало бы делать), я не могу контролировать, насколько глубоко кто-то другой решит вложить мой элемент управления. Гнездование должно работать. Стыковка должна сработать.

Sergey Alexandrovich Kryukov

Вы правы. Вам действительно нужно использовать док и гнездо так глубоко, как вы хотите; и хорошее гнездование-хороший знак. Тем не менее, макет легко испортить. Проблема, вероятно, не в коде пользовательского интерфейса, а в ИТ-дизайнере-он иногда "помогает" все испортить...
--СА

ChewsHumans

Ну, я искал до тех пор, пока мои глаза не начали кровоточить, и ничего не нашел. Я полагаю, вы не могли бы взглянуть на проект и посмотреть, не придет ли вам что-нибудь в голову? Я был бы вам очень признателен.

Sergey Alexandrovich Kryukov

У меня нет VB.NET установлен, извините. Это первое, что я удаляю из параметров установки при установке Visual Studio.

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

Удачи, счастливого Нового года.
--СА

4 Ответов

Рейтинг:
28

mjhetze

Это похоже на проблему, которую я только что исправил. Стек ядра слишком мал. Это ограничение Windows. В x64 Windows это происходит быстрее, чем в x86, так как адрес в два раза больше, но стек ядра остался прежним.

Для получения дополнительной информации (и обходного пути):

http://support.microsoft.com/kb/953934


ChewsHumans

Это сработало! Большое спасибо: я рвал на себе волосы из-за этого. Но один вопрос. Разве вы не должны предоставить исправление или что-то в этом роде? Например, изменить управление.OnSizeChanged функция в фреймворке, чтобы, например, вести подсчет рекурсии и использовать BeginInvoke() автоматически при достижении предела? Потому что выполнение этого для одного элемента управления в наследственности поможет только для конкретного приложения. Когда я напишу другое приложение, мне придется сделать это снова, потому что вложенность будет другой. Например, я могу не использовать панели, или панели могут быть близко к поверхности или очень глубоко.

mjhetze

Извините, я не совсем ясно выразился-я нашел ошибку и исправил ее в своем приложении; я не работаю в Microsoft. Есть запись в блоге MSDN, которая обсуждает это более подробно.

http://blogs.msdn.com/b/alejacma/archive/2008/11/20/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows-exceeds-a-certain-depth-x64.aspx?PageIndex=2

Было бы неплохо, если бы они как-нибудь подтолкнули его исправить.

ChewsHumans

Ах, простите, я не так понял. Спасибо за помощь.

Рейтинг:
2

Sergey Alexandrovich Kryukov

К сожалению, я не могу загрузить ваш проект прямо сейчас. Я могу дать вам несколько идей.

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

Например, как решить такую задачу:"сделать равномерную прокладку везде, а толщину прокладки определить в одном месте"? Только в коде. Дизайнер нарушает Не повторяйся (Сухой) принцип (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself[^]); таким образом, он не может быть законно использован в сложном и правильном пользовательском интерфейсе. С помощью дизайнера вы не можете по-настоящему увидеть макет. Элементы управления перекрывают друг друга; элемент управления с DockStyle.None может быть выровнен как пристыкованный и выглядит как пристыкованный. В принципе, вам нужно держать все элементы управления состыкованными.

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

Я часто использую одну простую схему: с помощью дизайнера я добавляю только строку состояния, главное меню и одну главную панель в центре, заполняя пространство, чем добавляю панели в эту главную панель. Все остальное делается в коде.

—СА


ChewsHumans

Да, вы делаете правильные выводы. Однако я не верю, что дизайнер виноват в этой проблеме. Я думаю, что есть ошибка в самом коде компоновки фреймворка.

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

Рейтинг:
1

Rajeev Jayaram

Ну, вот вам реализация вложенной стыковки с открытым исходным кодом. Попробуйте загрузить это приложение и если эта аналогичная реализация поможет Вам разобраться в вашей проблеме, http://sourceforge.net/projects/dockpanelsuite/[^]


ChewsHumans

Хотя это интересный проект - и тот, который я могу использовать в своих собственных приложениях, - его цель состоит не в том, чтобы заменить функциональность стыковки в Windows Forms, а скорее в том, чтобы позволить панелям быть закрепленными, вкладками и плавающими аналогично окнам инструментов Visual Studio. Полезно-да, но не имеет никакого отношения к моей проблеме. Спасибо за предложение - как я уже сказал, я могу найти его полезным, но это не поможет решить мою проблему.

Рейтинг:
0

atakan ardic

перейдите в меню окна и нажмите кнопку Сбросить макет окна..
это-верное решение..