Здравствуйте, Alexander Polyakov, Вы писали:
AP>Скриншот для указанной мной формы рисовал профессиональный дизайнер. Требуется в точности соблюсти все задумки дизайнера. Если какие-то правила лайаута не видны из рисунка, их можно уточнить у дизайнера (сейчас можно спросить у меня или посмотреть в C# код). Сейчас ваша реализация выглядит некрасиво. Отмазка, что Вы не прописывали все детали, не катит, поскольку кода Вы написали уже больше, чем в моей C# реализации.
Офигеть. Напоминает подход некоторых ПМ. Вам продемонстрировали принципиальную вещь. О соответствии разметке или чему-либо еще речи не шло. AP>То, что увидел при первом просмотре: AP>1. Текст “Fax:” должен быть прижат к правому краю.
Я в курсе. Больше 15 минут на данный пример тратить не хотелось. AP>2. В оригинале текст “State\province:” выдавливает свой текстбокс вправо. Но при этом текстбоксы для Fax и Country выровнены по линии. AP>3. Ширина колонки для лейблов должна выравниваться по максимальному тексту в колонке. У Вас же тупо захарткожено Width="100", причем для обоих колонок (ширина колонок необязательно одинакова). AP>4. Все три шрифта (в заголовке секции, в лайблах, в текстбоксах) должны иметь одни и те же FontFamily=”Tahoma” Font Size=”11”.
AP>Остальные комментарии позже.
Речь шла о темплейтах вроде как. Вы что написали? "Меня особенно интересует, как обойтись без копипаста". Вам написали аж два варианта(у Владека красивее). Теперь начались претензии по лайауту. Интересно, что будет дальше. У меня впечатление, что мы дальше и дальше отодвигаемся от темы беседы и скатываемся в обсуждение мелочей.
Пройдусь-ка по вашей реализации:
1.
new Grid().ColumnDefinitions(
new ColumnDefinition(),
new ColumnDefinition().Width(18),
new ColumnDefinition()).Nested(
Section("Customer", CustomerSection()).Grid_Position(0, 0),
Section("Dealer", DealerSection()).Grid_Position(0, 2))
Это будет себя вести не слишком правильно при ресайзе. Хардкод выделен.
2.
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto(),
new RowDefinition().Height_Auto()).ColumnDefinitions(
new ColumnDefinition().Width_Auto(),
new ColumnDefinition(),
new ColumnDefinition().Width_Auto(),
Разметка в подобном стиле тоже ни к чему хорошему не приведет.
3.
private static TextBlock TextBlock(int row, int column)
{
return new TextBlock().Grid_Position(row, column).Margin(5, 0, 5, 0)
.MaxWidth(75).TextWrapping_Wrap().Execute(SetFontStyle)
.VerticalAlignment_Center();
}
Ну тут кагбэ тоже понятно. Вы мне тут где-то выше про хардкод писали, ога.
N>Ну и потом, почитайте, например документацию к FrameworkElementFactory — не все можно создать в коде просто по определению. N>ТОЛЬКО загрузить из xaml,
С этим история была такая. Про FrameworkElementFactory я прочитал еще почти в самом начале и подумывал об отказе от этого проекта. Но потом случайно наткнулся на вот эту статью и все же продолжил заниматься проектом. А вчера натолкнулся на то, что через FrameworkElementFactory нельзя установить Grid.RowDefinitions, поскольку это свойство не является dependency property. Но оказалось, что FrameworkElementFactory можно не использовать, а использовать вот такой метод
public static DataTemplate ToDataTemplate(this object obj)
{
return (DataTemplate)
XamlReader.Load(
XmlReader.Create(
new StringReader(
string.Format(
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</DataTemplate>",
XamlWriter.Save(obj)))));
}
C>Теперь начались претензии по лайауту. Интересно, что будет дальше. У меня впечатление, что мы дальше и дальше отодвигаемся от темы беседы и скатываемся в обсуждение мелочей.
Вы можете потратить еще несколько минут и внести исправления с учетом моих 4-х замечаний? Это может оказаться принципиальным.
AP>>4. Все три шрифта (в заголовке секции, в лайблах, в текстбоксах) должны иметь одни и те же FontFamily=”Tahoma” Font Size=”11”. N>вот по этому пункту, сдается мне, достаточно все упоминания шрифтов в разных элементах поудалять и один раз в свойствах страницы написать FontFamily и FontSize.
Известно, что использование наследования стиля через дерево элементов хуже при внесении изменений. В этом случае сложнее смотреть, откуда пришло то или иное значение стиля. Лучше явно прописывать, тогда простой Find Usage поможет вам увидеть что где используется и внести изменения так, чтобы ничего не поломать.
AP>>>4. Все три шрифта (в заголовке секции, в лайблах, в текстбоксах) должны иметь одни и те же FontFamily=”Tahoma” Font Size=”11”. N>>вот по этому пункту, сдается мне, достаточно все упоминания шрифтов в разных элементах поудалять и один раз в свойствах страницы написать FontFamily и FontSize. AP>Известно, что использование наследования стиля через дерево элементов хуже при внесении изменений. В этом случае сложнее смотреть, откуда пришло то или иное значение стиля. Лучше явно прописывать, тогда простой Find Usage поможет вам увидеть что где используется и внести изменения так, чтобы ничего не поломать.
Откуда это известно? Вы с WinForms работали? Там тоже каждому элементу руками шрифт прописывали? Или все-таки иногда достаточно было того, что шрифт для всей формы задан? А чем хуже-то? Если надо изменить шрифт для всей формы, что лучше — сделать это в одном месте один раз, или с find usage 33 раза?
По-моему, вы не поймете чужих объяснений, пока не попробуете самостоятельно свои две формочки в xaml'е сделать.
Возьмите пример Vladek'а и доведите до идеального состояния. Что не нравится — спрашивайте как исправить. Пока что вы по верхам скачете типа "Пастернака не читал, но осуждаю".
N>Вы с WinForms работали?
Я работал и с WinForms и c HTML/CSS. WinForms как layout engine это убожество.
N>Если надо изменить шрифт для всей формы, что лучше — сделать это в одном месте один раз, или с find usage 33 раза?
В 33 местах стоят ссылки, а значение храниться в одном месте. Find Usage вам показывает, где это используется, вы просматриваете, затем в 31 месте оставляете как есть, а в 2-х местах ставите новое значение или ссылку.
Здравствуйте, notacat, Вы писали:
N>По-моему, вы не поймете чужих объяснений, пока не попробуете самостоятельно свои две формочки в xaml'е сделать. N>Возьмите пример Vladek'а и доведите до идеального состояния.
Кстати да. Там довольно странный лайаут для state\province на скриншоте. Не знаю, насколько дизайнер профессионален, но в глаза бросается сильно.
Кароч. Финальная моя версия. Со state\province возиться не стал, потому что там разметка выглядит странно, мягко говоря. Более заниматься данным примером не буду. Автор топика, судя по всему- начинающий форумный тролль.
C>Кароч. Финальная моя версия. Со state\province возиться не стал, потому что там разметка выглядит странно, мягко говоря. Более заниматься данным примером не буду. Автор топика, судя по всему- начинающий форумный тролль.
Извиняюсь, просто хотелось получить побольше кода для сравнения. Это не совсем получилось, ну да ладно, остановимся на том, что уже написали.
Вернемся к вопросу реюза разметки для двух секций. Вы воспользовались готовыми GroupBox (а Vladek контролом HeaderedItemsControl). В принципе задача решена, но в этом решении не просматривается прием, который можно было бы применять в похожих задачках. WPF темплетирование, конечно, придает достаточно широкую гибкость, но все же при использовании конкретных контролов GroupBox и HeaderedItemsControl вы (возможно не отдавая в этом себе отчет) завязываетесь на специфику этих контролов. Т.е. в силу применяемого технического решения вносите лишние, не обусловленные самой задачей ограничения. А это порочная стратегия. Специфика контрола GroupBox состоит в том, он может принимать всего два “параметра” Header и вложенный Content. А что если потребуется передавать третий параметр? Например, надо будет разместить картинку вдоль правой вертикальной границы секции. Картинка должна указываться как параметр секции. В итоге вы придете к решению аля “master page”, описано, например, тут http://www.codeproject.com/KB/WPF/WPFMasterPageControl.aspx
Как я уже неоднократно писал, это слишком громоздко для такой простой проблемы. На C#-е это выльется просто в добавление третьего параметра в метод Section.
Здравствуйте, Alexander Polyakov, Вы писали:
C>>Кароч. Финальная моя версия. Со state\province возиться не стал, потому что там разметка выглядит странно, мягко говоря. Более заниматься данным примером не буду. Автор топика, судя по всему- начинающий форумный тролль. AP>Извиняюсь, просто хотелось получить побольше кода для сравнения. Это не совсем получилось, ну да ладно, остановимся на том, что уже написали.
AP>Вернемся к вопросу реюза разметки для двух секций. Вы воспользовались готовыми GroupBox (а Vladek контролом HeaderedItemsControl). В принципе задача решена, но в этом решении не просматривается прием, который можно было бы применять в похожих задачках. WPF темплетирование, конечно, придает достаточно широкую гибкость, но все же при использовании конкретных контролов GroupBox и HeaderedItemsControl вы (возможно не отдавая в этом себе отчет) завязываетесь на специфику этих контролов. Т.е. в силу применяемого технического решения вносите лишние, не обусловленные самой задачей ограничения. А это порочная стратегия. Специфика контрола GroupBox состоит в том, он может принимать всего два “параметра” Header и вложенный Content. А что если потребуется передавать третий параметр? Например, надо будет разместить картинку вдоль правой вертикальной границы секции. Картинка должна указываться как параметр секции. В итоге вы придете к решению аля “master page”, описано, например, тут http://www.codeproject.com/KB/WPF/WPFMasterPageControl.aspx AP>Как я уже неоднократно писал, это слишком громоздко для такой простой проблемы. На C#-е это выльется просто в добавление третьего параметра в метод Section.
По существу есть чего сказать? Или опять общие фразы из серии "не читал, но осуждаю"? Вы сами-то понимаете, насколько феерический бред Вы сейчас несете?
Реальная задача(с реальными объектами) решается несколько по-другому.WPF тем и хорош, что практически любую задачу можно решить несколькими способами.GroupBox(или HeaderedContentControl) взят для удобства.В общем, что я собственно хотел до вас донести, товарисч: вы можете сколько угодно допиливать свою реализацию XAML — вводить новые аргументы, параметры и т.д., но требуемой гибкости вы не достигнете никогда.
Тут еще куча вопросов неохваченных осталась:
1. Custom MarkupExtensions. Как их реализовывать.
2. Биндинги во всем их многообразии
3. Команды(куда ж без них)
4. Конвертеры
А про картинку как "параметр секции" мне тут заливать не надо. В большинстве сценариев ее можно реализовать внутри конкретного темплейта. В общем, утомился я что-то с Вами спорить, уважаемый. Я Вам про одно толкую, Вы мне совсем про другое. В общем, судя по всему, опыта в WPF у Вас прискорбно мало, что не может радовать в свете данной дискуссии.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>В принципе, может быть, достаточно создать общий темплетированный контрол скажем с 5-ю параметрами. Arg1, Arg2, …, Arg5.
Офигенный подход. Давайте еще создадим контрол с 40 параметрами. На все случаи жизни, так сказать. Или, как .Net 4.0 выйдет, Tuples туда прифигачим.
Здравствуйте, Alexander Polyakov, Вы писали:
AP>Вернемся к вопросу реюза разметки для двух секций. Вы воспользовались готовыми GroupBox (а Vladek контролом HeaderedItemsControl). В принципе задача решена, но в этом решении не просматривается прием, который можно было бы применять в похожих задачках. WPF темплетирование, конечно, придает достаточно широкую гибкость, но все же при использовании конкретных контролов GroupBox и HeaderedItemsControl вы (возможно не отдавая в этом себе отчет) завязываетесь на специфику этих контролов. Т.е. в силу применяемого технического решения вносите лишние, не обусловленные самой задачей ограничения. А это порочная стратегия. Специфика контрола GroupBox состоит в том, он может принимать всего два “параметра” Header и вложенный Content.
Здесь только одни возможности: этот контрол (а GroupBox отличается от HeaderedContentControl только своим видом в стиле визуальной темы ОС) представляет собой нечто, что имеет заголовок и содержимое. А всё остальное не ограничивается.
AP>А что если потребуется передавать третий параметр? Например, надо будет разместить картинку вдоль правой вертикальной границы секции. Картинка должна указываться как параметр секции.
Это будет частью шаблона контрола или частью содержимого контрола, которое в свою очередь будет состоять из подобного же контрола с заголовком, который (заголовок) будет представлен в виде картинки. Это всего лишь вопрос подходящей декомпозиции конечного результата на исходные составляющие и использование принципа самоподобия.
AP>В итоге вы придете к решению аля “master page”, описано, например, тут http://www.codeproject.com/KB/WPF/WPFMasterPageControl.aspx AP>Как я уже неоднократно писал, это слишком громоздко для такой простой проблемы. На C#-е это выльется просто в добавление третьего параметра в метод Section.
Если решение хоть и громоздкое, но его легко использовать — это хорошее решение. Master page из статьи, например, можно сделать с помошью двух HeaderedContentControl-ов, один из которых будет служить заголовком для второго. Принцип самоподобия и уместная декомпозиция.
V>...или частью содержимого контрола, которое в свою очередь будет состоять из подобного же контрола с заголовком, который (заголовок) будет представлен в виде картинки. Это всего лишь вопрос подходящей декомпозиции конечного результата на исходные составляющие и использование принципа самоподобия.
У Вас каждая из двух секций Customer и Dealer будет повторять вложение двух HeaderedItemsControl-ов друг в друга? Это и есть копипаст и неудобства развития и сопровождения.
Например, перемещение картинки внутрь первого заголовка у вас приведет к рефакторингу обеих секций Customer и Dealer. А в “логически чистой” реализации должно приводить только к рефакторингу тела самой секции (в одном месте); места использования секции не должны затрагиваться при внесении такого изменения.
Сделаю небольшое замечание. В задаче явно фигурирует понятие секции. Структура программного кода должна отражать это понятие (Это базовый принцип программирования). Если в каждом месте использовать по паре вложенных HeaderedItemsControl-ов, то в коде отсутствует понятие секции. Тем самым Вы пытаетесь не видеть понятия секции в задаче. Т.е. неправильная декомпозиция задачи на подзадачи. Отсюда и получаем стандартные следствия неправильной декомпозиции.
Делать такие вещи Вас заставляет выбранная технология -- XAML. А это одно из самых печальных явлений, когда не задача, а технология/инструмент ведет вас. Печально, потому что многие люди не отдают себе в этом отчет.
Здравствуйте, Alexander Polyakov, Вы писали:
V>>...или частью содержимого контрола, которое в свою очередь будет состоять из подобного же контрола с заголовком, который (заголовок) будет представлен в виде картинки. Это всего лишь вопрос подходящей декомпозиции конечного результата на исходные составляющие и использование принципа самоподобия. AP>У Вас каждая из двух секций Customer и Dealer будет повторять вложение двух HeaderedItemsControl-ов друг в друга? Это и есть копипаст и неудобства развития и сопровождения.
AP>Например, перемещение картинки внутрь первого заголовка у вас приведет к рефакторингу обеих секций Customer и Dealer. А в “логически чистой” реализации должно приводить только к рефакторингу тела самой секции (в одном месте); места использования секции не должны затрагиваться при внесении такого изменения.
AP>Сделаю небольшое замечание. В задаче явно фигурирует понятие секции. Структура программного кода должна отражать это понятие (Это базовый принцип программирования). Если в каждом месте использовать по паре вложенных HeaderedItemsControl-ов, то в коде отсутствует понятие секции. Тем самым Вы пытаетесь не видеть понятия секции в задаче. Т.е. неправильная декомпозиция задачи на подзадачи. Отсюда и получаем стандартные следствия неправильной декомпозиции.
AP>Делать такие вещи Вас заставляет выбранная технология -- XAML. А это одно из самых печальных явлений, когда не задача, а технология/инструмент ведет вас. Печально, потому что многие люди не отдают себе в этом отчет.
Жесть какая.Посмеялся, честно говоря. Диагноз ясен, озвучивать не буду.
AP>Сделаю небольшое замечание. В задаче явно фигурирует понятие секции. Структура программного кода должна отражать это понятие (Это базовый принцип программирования). Если в каждом месте использовать по паре вложенных HeaderedItemsControl-ов, то в коде отсутствует понятие секции. Тем самым Вы пытаетесь не видеть понятия секции в задаче. Т.е. неправильная декомпозиция задачи на подзадачи. Отсюда и получаем стандартные следствия неправильной декомпозиции.
Вы уж определитесь — мы в форуме что-то обсуждаем, или вы нас при приеме на работу тестируете? Никто себе не ставил целью Вашу задачу декомпозировать и тем более телепатией заниматься. Если вам очень хотелось иметь в примерах замла это понятие — надо было об этом писать ДО того, а не ПОСЛЕ.
Даю подсказку. Если очень хочется иметь понятие секции, пишется свой контрольчик с названием Секция и имеете счастье. Это просто — чуть-чуть кода и может быть чуть-чуть xaml'а. Главное правильно выбрать, от чего унаследоваться.
Вы не пытайтесь убедить других, что xaml плох, вы попытайтесь лучше понять, почему они с вами не согласны.
Может другим путем пойти? Давайте попросим кого-нибудь выложить хороший с его точки зрения пример на xaml'е с перечнем требований типа — никаких явных заданий свойств в каждом месте, плавающая разметка, возможность отдать отдельную часть работы дизайнеру на причесывание, и т.п.
А вы все это реализуете в коде. Вот потом и посравниваем, что получится.
Здравствуйте, Alexander Polyakov, Вы писали:
V>>...или частью содержимого контрола, которое в свою очередь будет состоять из подобного же контрола с заголовком, который (заголовок) будет представлен в виде картинки. Это всего лишь вопрос подходящей декомпозиции конечного результата на исходные составляющие и использование принципа самоподобия. AP>У Вас каждая из двух секций Customer и Dealer будет повторять вложение двух HeaderedItemsControl-ов друг в друга? Это и есть копипаст и неудобства развития и сопровождения.
Если секции будут подобны, они будут сделаны с помощью общего шаблона.
AP>Например, перемещение картинки внутрь первого заголовка у вас приведет к рефакторингу обеих секций Customer и Dealer. А в “логически чистой” реализации должно приводить только к рефакторингу тела самой секции (в одном месте); места использования секции не должны затрагиваться при внесении такого изменения.
Если шаблон будет общим, рефакторинг коснётся только его.
AP>Сделаю небольшое замечание. В задаче явно фигурирует понятие секции. Структура программного кода должна отражать это понятие (Это базовый принцип программирования). Если в каждом месте использовать по паре вложенных HeaderedItemsControl-ов, то в коде отсутствует понятие секции. Тем самым Вы пытаетесь не видеть понятия секции в задаче. Т.е. неправильная декомпозиция задачи на подзадачи. Отсюда и получаем стандартные следствия неправильной декомпозиции.
Не путайте модель предметной области и элементы интерфейса. Имея в виду пример, рискну предположить, что Customer и Dealer являются частью модели предметной области, а секция относится к интерфейсу. И да, тогда понятие секции в коде фигурировать не будет, там будут только классы Customer и Dealer. Зато в XAML будет описано как именно отображать такие объекты, как Customer или Dealer — в виде секций или как-нибудь ещё.
Другими словами, каждый слой моделирования задачи обладает своей степью абстракции. Чем ближе к интерфейсу, тем абстракции конкретнее и подробнее. Например: в сделке принимают участие клиент и торговец, участники сделки отображаются на экране в виде секций. Одна цель — совершить акт сделки, другая — отобразить детали её совершения. Первое — относится к предметной области задачи, второе — к интерфейсу. Секция не участвует в сделке, в предметной области ей не место, понятие секции возникает лишь при отображении заказчика и торговца.
AP>Делать такие вещи Вас заставляет выбранная технология -- XAML. А это одно из самых печальных явлений, когда не задача, а технология/инструмент ведет вас. Печально, потому что многие люди не отдают себе в этом отчет.
WPF наоборот позволяет использовать такой замечательный архитектурный шаблон, как Model-View-ViewModel, благодаря шаблонам данных и связыванию данных, что ведёт к полному разграничению модели предметной области и элементов интерфейса.
Здравствуйте, Alexander Polyakov, Вы писали:
C>>Жесть какая.Посмеялся, честно говоря. Диагноз ясен, озвучивать не буду. AP>Вы, действительно, не видите дублирование кода?
Вам более компетентные и выдержанные товарищи уже ответили.Не путайте божий дар с яичницей, уважаемый. Как правильно сказали выше, в данной задаче к предметной области относятся Customer и Dealer, остальное не более чем отображение. С какого перепоя я должен вводить в предметную область Section, неясно. А если завтра UI радикально поменяется, и надо будет отображать данные совсем по-другому(а такое случается, особенно на стадии прототипирования)?Вы тут много и пространно говорите о дублировании кода, копипасте и т.п., не учитывая одной простой вещи — ваш код, в принципе, тот же копипаст. Потому как с вашей точки зрения два разных темплейта, определенных для одного объекта — это уже копипаст. Третий темплейт — уже зло, не так ли? С моей точки зрения зло — плодить лишние сущности в коде, чрезмерно усложняя и раздувая его. То, что может быть сделано в XAML — должно быть там сделано. Нельзя логику отображения мешать с остальным кодом. Нельзя связывать объекты с их отображением, потому что один и тот же объект может быть отображен сотней-другой разных способов(в одном и том же проекте причем).И последнее. Стиль общения, имхо, стоит сменить на более нейтральный. На этом форуме Вам никто ничего не должен. То, что люди делают, они делают из интереса, а не потому, что их кто-то заставляет. Опять же, не стоит путать вещи, принципиальные для дискуссии, с вещами непринципиальными(типа разметки, которой Вы, если честно, выели мне мозг).
Я очень не завидую Вашим подчиненным, если они у Вас есть.