Pull to refresh

Comments 226

UFO just landed and posted this here
С тех пор мало что поменялось, поэтому ваши знания не устарели. :)

Ну вот допустим мне нужен список, где каждый элемент содержит два чекбокса, забинденных на некоторые свойства какого-то объекта какой-то коллекции. Кто должен писать шаблон элемента списка? Дизайнер? Где ж такого дизайнера взять, который не только с XAML на «ты», но ещё и смыслит в шаблонах, стилях, триггерах и т.п.? Маловероятно. В лучшем случае два чекбокса нарисует в Бленде, в худшем случае будет макет в фотошопе. Но даже если сферический дизайнер в вакууме одолеет шаблон, то биндинги всё равно программисту прописывать в XAML'е.

И это мы рассмотрели тривиальный случай. А если дерево рисуем со сложной логикой? Тут дизайнеру при всей его сферичности не отдать написание шаблонов и стилей, потому что в них оказывается слишком много логики.
UFO just landed and posted this here
Не знаю, что там как позиционируется, но редактор WPF в VS как пять лет назад жрал память, зависал, падал и вообще был непригоден к рисованию формы сложнее, чем «две внопки на панели», так и сейчас совершенно бесполезен. Бленд несколько более адекватен, но это не спасает. Да и к последней студии его пока не выпустили. В общем, печаль с гуями.
UFO just landed and posted this here
Это только внешне XML. А как начинаешь разбирать — оказывается, что часть информации определяется с помощью reflection, часть лежит в атрибутах а-ля "{Binding Path.(ns:To.Property).Name, RelativeSource={Relative Source AncestorType={x:Type Button}, AncestorLevel=2}, Convertor={StaticResource MyConverter}, StringFormat={}{0:abc} ...}" (LISP отдыхает), часть информации лежит глубоко в кишках фреймворка и никак не вытаскивается… И ведь все шаблоны-стили ещё надо осмысленно показать визуально — при том, что байндинги в коде везде предполагают существование каких-то данных.

Так что, подозреваю, это всё архисложно.
UFO just landed and posted this here
Такой биндинг только в крайних и исключительных случаях. Обычно пишется что-то типа "{Binding Price}" и всё. Или, если очень надо, сделать обычного наследника от стандартного Binding, в котором это всё прописать.
Конвертеры очень часто нужны, к ним относительно часто нужны параметры. И вот уже "{Binding Path, Converter={StaticResource MyConverter}, ConverterParameter={StaticResource MyParameter}}". Потом хочется валидации. И обновления по мере вводе текста. И пошло-поехало…

Пробовал я с наследниками. Они имеют свойство работать не всегда и с глюками. :) То first chance exception'ы начинаются внутрях сыпаться гроздями, то ещё что… Да и возможности markup extensions весьма ограничены из-за компилируемости XAML и недоступности внутренностей фреймворка — что-то сложнее избавления от имени параметра или трансформации строчки написать нереально.
Если у Вас такой байдинг только в исключительных случаях, то вам форму можно и в редакторе vs формочки рисовать.
И? Это ж удобнее по идее. Не думаю, что они испортят его в процессе переноса в студию. Главное, чтоб не только для ультимейт какой-нибудь.
Если в студии будет Бленд, а не текущее багло, если будет единая среда, то это круто. Осталось дотянуть до апдейта. :)
Например, при написании шаблонов — их студийный редактор, как не поддерживал, так и не поддерживает. А прописать с первого раза корректный биндинг свойств для более-менее сложной формы и вовсе тяжело.
Нет абсолютно никакой причины писать XAML руками. Изучайте Blend, к счастью, этот инструмент можно выучить меньше чем за неделю, а времени он вам экономить будет целый вагон.
Поправить какие-то значения до pixelPrefect проще в xaml.

Стили глобально всегда в бленде правлю, но почти всегда затем подправляю ручками.
Совершенно не согласен. Только сочетая Blend и ручное редактирование XAML можно работать эффективно. Я уже молчу о конвертерах, биндингах, Behaviours и других вещах, которые через Blend задать или невозможно, или очень неэффективно.
Для примитивных форм вполне можно обойтись даже редактором Visual Studio 2010, а для построения более-менее развитых форм нужно уметь и ручками работать.
Я не говорю, что нужно использовать только Blend, конечно проще некоторые вещи в блокноте подправить. Но без Blend-а сложно и в случае более-менее красивой\сложной формы, так и совсем не обойтись.
А что мешает просто взять Qt5 + qml?
В следующих релизах ожидается поддержка winRT. А как бонус ещё и iOS, Android и вообще те платформы, которые ещё не придумали?
Я вообще был уверен, что у WPF дела получше и только XAML его уродует.
Не знаю, есть ли Qt под .NET, но родной для него ведь С++. Не думаю, что что-то хорошее выйдет, если на шарпе писать. А писать на плюсах я не хочу, я к вкусностям шарпа слишком привык, в плюсах чувствую себя неуютно.

Кросс-платформенность — это, конечно, хорошо, но пока лично мне не нужна, софт не предназначен для планшетов-мобилок. Да и даже если так, то всё равно UI с нуля переделывать.
Есть (4-й). code.google.com/p/qt4dotnet/ и api.kde.org/qyoto-api/ Вообще посмотрите www.mono-project.com/Gui_Toolkits — если работает под Mono, то должно работать и под «нативным» .NET. Правда для своих небольших тулз я выбрал GTK#, но вроде не слышал о проблемах при запуске под виндами
Хочется работать с .Net и C#. Всякий раз когда пишу разметку на XAML, вспоминаю с грустью qml и надеюсь что когда-нибудь XAML эволюционирует во что-то подобное. Много писал и на том и на том.
С точки зрения возможностей Qt+qml уступает в чём-нибудь WPF? Стили, контрол темплейты, дата темплейты, впихивание любого контрола в любой контрол, прочее?
Лучше что-нибудь наподобие Jade или Slim.
Qt — это хорошо, если можно было бы писать нормально на C#. Но у меня так и не получилось скомпилить Qyoto (если кто смог, отпишитесь в личку!).
Я не знаю обманул ли меня коллега, но он вычитал, что лицензия на QT, чтобы компания могла разрабатывать коммерческое ПО стоит очень дорого (за 100к).

Это правда? И если правда, то, возможно, это является причиной того, почему не все могли бы пользоваться QT?
Вот цены годовой давности в евро (согласно какому-то чуваку с какого-то форума, который не поленился и позвонил — эти обормоты не пишут цены на сайте, настолько они невменяемые):

Qt Desktop Single OS – 2.995,-
Qt Desktop Multi OS – 4.195,-
Qt Embedded Single – 4.795,-
Qt Embedded Multi – 5.595,-
Qt All OS – 6.395,-

То есть цена даже не 100 000, а 250 000. %)
Там, конечно, есть какие-то тонкости с LGPL, но, как мы поняли, нельзя пользоваться LGPL, если ты хочешь обладать полными правами на своё ПО и держать всё закрытым.

Хотя с другой стороны, что такое ~200k для компании, разрабатывающей проприетарное ПО?

Но с другой же стороны представьте ситуацию.
Наш отдел 3,5 программиста (0,5 программиста — это студент). У каждого лицензия VS2010.
Заходит шеф, а мы ему:
— «Шеф, ты знаешь, WPF — шлак, мы хотим QT.»
-«Я рад, что вы стремитесь к лучшему. Сколько будет стоить переход?»
-"~200k на лицензию."
-Вы совсем что-ли ох****, идите на *у*

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

Как сказал мой опытный коллега, если ты пользуешься Microsoft, то лучше использовать ВСЁ от Microsoft.
Если юзаешь VS, то юзай TFS. Юзаешь TFS — юзай Microsoft Office. Юзаешь VS — юзай SQL Server.
Ну и так далее.
Хотя с другой стороны, что такое ~200k для компании, разрабатывающей проприетарное ПО?

Для компании — да. А как насчёт независимых разработчиков? На них всем глубоко покласть.

Как сказал мой опытный коллега, если ты пользуешься Microsoft, то лучше использовать ВСЁ от Microsoft.

Часто очень правильная стратегия. Лучше поддерживается, лучше совмещается.
Независимые программисты вообще ничего не платят, их устраивает LGPL лицензия. Там не такие уж и большие ограничения, вполне можно делать закрытые приложения без проблем.
> нельзя пользоваться LGPL, если ты хочешь обладать полными правами на своё ПО и держать всё закрытым
А смысл так поступать? Вы LGPL читали?
Только не TFS! Мне приходится работать сейчас с ним в одном проекте, в остальных SVN. Так что сравнивать приходится каждый день. Еще ни разу сравнение не было в пользу TFS. Единственное уточнение: TFS используется только как система контроля версий. Возможно, использование других возможностей дает какие-то преимущества.
TFS раскрывается, только если использовать все в комплексе.Work Item tracing, билды, управление тестированием, отчеты и проч. Source Control там действительно «обычный», только для него использовать просто нет смысла.
Возможно станет лучше если прикрутят к TFS'у GIT
Поправьте меня если ошибаюсь, но на сколько я понимаю, то что написали Вы будет распространяться под той лицензией, под которой Вы захотите. LGPL не дает Вам возможности изменить и потом закрыть сами библиотеки Qt которых Вы и не писали. В случае с WPF, как я понимаю, свободы распоряжаться лицензией на сторонние библиотеки от Microsoft у Вас тоже нет.

The LGPL allows developers and companies to use and integrate LGPL software into their own (even proprietary) software without being required (by the terms of a strong copyleft) to release the source code of their own software-parts.
en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
Большое спасибо! Значит мой коллега читал невнимательно. И за что меня заминусовал народ?!
эээ, а зачем при переходе с WPF на Qt брать Qt All OS, судя по всему тут нужен только Qt Desktop Single OS – 2.995.
Это во-первых, во-вторых я видел примеры, когда разработчики в компаниях пользовались купленными VS Ultimate по 200К за лицензию и в общем-то никого этот факт не смущает.
В-третьих, лицензия необходима только тем разработчикам, кто будет непосредственно разрабатывать GUI, если рассматривать его как замену WPF. Для тех, кто разрабатывает сервисную часть, установленный Qt не нужен, вполне достаточно бинарных поставок.

Qt распространяется под лицензией LGPL, что позволяет его использовать в любом ПО, даже коммерческом. Коммерческая лицензия для тех, кто делает правки в самом Qt, и не хочет открывать исходники; или же для тех, кто линкует Qt статически, не предоставляя obj файлов (поправьте, если что-то путаю).
Кстати, да. WPF ругают уже не первый год, интересно, как быстро появятся подобные статьи про QtQuick.
Там можно кое чего накопать, но в основном его ругают за отсутствие деревьев, за невозможность в моделях qmlных юзать qsTr и прочие плюшки (исправили в Qt5), некоторые сложности с компонентом текста, невозможно например из него выдрать QTextDocument и натравить на него подсветку синтаксиса и прочие плюшки. Ну и с компонентами пока все не идеально.
Но он развивается и развивается быстро, плюс я не слышал чтобы Quick ругали за плохую производительность.
Есть какая-нибудь хорошая статья с перечислением недоработок Quick? Интересно, что у конкурентов происходит. А то конкуренция от Qt — по сути единственная надежда на развитие WPF. :)
Не видел, но будет время могу попробовать написать.
Кстати, есть еще же javaFX, которая тоже похожа на WPF  и имеет похожий на qml синтаксис.
Статью обязательно напишите, будет интересно почитать!

Сколько видел десктоповых приложений на Джаве — все были с ужасным корявым интерфейсом, который даже не пытался выглядеть «по-виндовому». И когда кто-то где-то упоминает, что на Джаве можно писать под десктоп, со всех сторон слышатся стоны. Я, конечно, сам не пробовал, но впечатление уже сложилось. :) Правда всё виденное мной без этого JavaFX писалось, вроде. Надо будет глянуть, что за зверь, удовлетворить любопытство.
Из конкурентов еще можно вспомнить XULRunner от Мозиллы, правда по мне так это уже весьма старая и тормозная вещь. Не конкурент даже для WPFа.
На JavaFX я не видел ни одного живого проекта в дикой природе. По ходу она никакой известностью не пользуется.
PS
Oracle выпилили красивый JavaFX Script, который кстати визуально не всегда отличишь от qml, теперь там FXXML, который визуально ничуть не лучше, чем XAML. Таки дела. Энтерпрайз такой энтерпрайз.
Интересно, под каким официальным предлогом поменяли язык — всё-таки обратная совместимость идёт лесом, радикальное решение независимо от результата. Неужели, чтобы XSLT применять к гуям? %)
>Сколько видел десктоповых приложений на Джаве — все были с ужасным корявым интерфейсом
Все зависит от целей разработчика. При желании можно сделать быстро, красиво и нативно. Вот, например:
Realtime Information Graphics,
Graphics, animation and interaction with Processing [Tutorial],
XMind — Mind Mapping Software,
Visual Watermark (только для Mac).
В Qt5 Quick точно нет стандартного Drag-n-drop файлов извне.
«Написание XAML никогда не доставляло удовольствия...» шутка наверно.
Скажите честно, вам нравится писать
<Style x:Key="MyStyle" TargetType="ItemsControl">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemContainerTemplate>
        <StackPanel/>
      </ItemContainerTemplate>
    </Setter.Value>
  </Setter>
</Style>
?

Или в духе
Style { Key: "MyStyle", [
  ItemsPanel: {
    { StackPanel }
  }
]}
было бы всё-таки чуть лучше? :)
Не вижу принципиальной разницы, да, короче, но ксамл как-то строже и однородней…
а если сравнить с корректным аналогом?
{
  "Style": {
    "-Key": "MyStyle",
    "-TargetType": "ItemsControl",
    "Setter": {
      "-Property": "ItemsPanel",
      "Setter.Value": {
        "ItemContainerTemplate": {
          
        }
      }
    }
  }
}

Это не qml, это обычный json причем странно оформленный.
да, чтобы это был qml еще пара квадратных скобок нужна, Очень Важное Упущение
qml так никогда не оформляется. Дело не в квадратных скобках.
Бездумная автоматическая конвертация XML-JSON не спасёт XAML, просто закрывающие теги станут короче. Тут нужен более основательный подход.
Ну вот в qml тоже не чистый json
Behaviour on x {
...
}


ведь не валидный json, но выглядит очень удачно.
А как во втором варианте компилятор догадается подставить ItemsControl, Value, ItemContainerTemplate?
С выпиливанием TargetType, пожалуй, переусердствовал — в реалиях текущей архитектуры от атрибута не избавиться. Но ведь можно в CSS лепить любое свойство к любому элементу, и никаких исключений не возникает — что нельзя применить, то игнорируется.

На куче классов висит атрибут ContentPropertyAttribute, который определяет «свойство по умолчанию». Поэтому вы пишете содержимое окна сразу, а не внутри <Window.Items></Window.Items>. Почему атрибута нет на сеттере, для которого Value — очевидное «свойство по умолчанию», — для меня остаётся загадкой.

Тип свойства ItemsPanel — ItemsPanelTemplate, поэтому, если впихивается не наследник, то имя класса можно было бы опустить. Да и вообще, у ItemsPanelTemplate даже наследников нет. Это единственная вещь во всей Вселенной, которую можно туда засунуть.
т.е. вы предлагаете выпилить TargetType, а потом заставить компилятор угадывать тип ItemsPanel? Или через рефлекшн, с проглатыванием эксепшенов? Оно не так работает.

Вообще то XAML — это язык описания классов. Отсутствие ContentPropertyAttribute у класса Setter — это не проблема XAML как такового.
Да пусть будет TargetType, я не против. Монструозность приведённого кода возникает совсем не из-за него.
Дайте угадаю. Из отсутствия атрибута и отказе создателей XAML угадывать тип инстанциируемого класса по типу проперти, которая может быть и интерфейсом?
Вы много видели в WPF интерфейсов?
т.е. вы предлагаете просто запретить в XAML инициализировать проперти абстрактных типов и интерфейсов? Ну вариант, чо.
Кстати, а как вы видите синтаксис инициализацию проперти дефолтным типом с указанием каких то её пропертей? И как указывать, если я всё же хочу наследника?
// неявно без свойств
ItemsPanel: {
  { StackPanel }
}
// явно без свойств
ItemsPanel: MyItemsPanel {
  { StackPanel }
}
// неявно со свойствами
ItemsPanel: {
  Foo: "Bar",
  { StackPanel }
}
// явно со свойствами
ItemsPanel: MyItemsPanel {
  Foo: "Bar",
  { StackPanel }
}

Здесь используется не чистый JSON, а сферический «JSON с типами и смешанными объектами» в вакууме. Если втискиваться в рамки стандартного JSON, то код может получиться примерно таким:

// неявно без свойств
ItemsPanel: {
  Content: { StackPanel }
}
// явно без свойств
ItemsPanel: {
  $type: "MyItemsPanel",
  Content: { StackPanel }
}
// неявно со свойствами
ItemsPanel: {
  Foo: "Bar",
  Content: { StackPanel }
}
// явно со свойствами
ItemsPanel: {
  $type: "MyItemsPanel",
  Foo: "Bar",
  Content: { StackPanel }
}

Можно по вкусу дать свойствам «тип» и «контент по умолчанию» какие-то общие краткие имена. Но, по-моему, немного улучшенный JSON был бы более удобен.
т.е. получается
и, соответственно,?
«Тупой парсер!» © ? :)
т.е. получается <Setter Property=«ItemsPanel» Value="{ItemContainerTemplate {StackPanel}}" />

и, соответственно, <Setter Property=«ItemsPanel» Value="{{StackPanel}}" />?

А про парсер я промолчу. Но кавычки шикарно расставил ящитаю.
Первый вариант: Тут с одной стороны избыточность кода, но зато структурировано и более читабельно.
Второй вариант: Мало кода (на первый взгляд, пока контрол примитивен, нет сложных биндингов и логики), то же самое с читаемостью.

Ни один из вариантов не идеален. Но хочется что то более удобного чем сейчас.
Этот пример в qml вообще не скомпилируется. Не могут быть имена свойств с большой буквы записываться.
Это не QML, это сферический JSON-XAML в вакууме. :)
Может я какой-то особенный, но для меня XML во многих случаях более читаемый чем JSON. Конечно в многом это зависти и от конкретных структур и от привычки.

Когда читал данные от тви, XML был более понятен, чем JSON
JSON не предназначен для записи и чтения человеком.

Смотрите в сторону YAML, Jade.
Смотрел я в сторону YAML. Он скорее мёртв, чем жив. :( Найти реально работающую библиотеку, поддерживающую последнюю спецификацию — невозможно ни для одного языка (кроме Руби, наверное). Да и слышал, что сами рубисты YAML перестали уважать.

JSON вполне читаем людьми. Ну да, условно-обязательные кавычки вокруг имён атрибутов. Ну да, для сохранения типа объекта каждый придумывает костыли. Но в целом и писать можно без проблем, и читать. Избыточности как в XML нет (правда и редакторов с автодополнением по схеме тоже нет, но это уже другая история).
Пробовали перейти на WPF. Да, современно… НО.

Таблица контактов с 2000 записями отжирала 60-70 % CPU не говоря уже о памяти. Клиенты на нетбуках типа eee pc и офисных моноблоках как то не оценили диких тормозов даже в простенькой программке. Тормозит все. И стандартные контролы и DevExpress и Telerik. Чем думали в отделе разработки WPF непонятно. Видимо их надо было пересадить на компы с 1-2 гигами оперативки и простенькими процами.

О портировании WPF на Mono речи не идет, а Mono уже не просто игрушка а вполне себе рабочий инструмент кросс платформы.

Так что только WinForms, только хардкор.

Автор прав насчет ASP.NET MVC. С каждым релизом технология все круче, кода все меньше а возможностей все больше. А в десктопе все тот же тормозной WPF и дико избыточный XAML. Печалька :(
Виртуализация не помогала? Её не очень тривиально настраивать (ну, обратная совместимость же), для длинных списков обязательно recycling.
2000? ерунда, просто включите виртуализацию, а вот если нельзя — начнутся проблемы…
не помогало. И вообще — проц начинает жраться просто при движении мышкой над гридом.
Вы что-то не так делали. Это очень нехарактерное поведение. Надо очень постараться, чтобы от движения мыши что-то тормозило.
да ладно, повесить на что-нибудь стандартную команду, которая на каждый чих кидает CanExecuteChanged, вот и тормоза на гриде.
Сталкивался с таким не раз и не два.
виртуализация может не работать, например если включена группировка
Это ещё не исправили? VisrtualizingStackPanel допилили же.
на 4-м — еще не исправили
Если так — прогоните профайлером. 2000 без виртуализации только при инициализации тормозить будут, тут скорее какие-то лишние события.
Сам WPF не тормозит. Просто приготовить по человечески контролы довольно сложно. + Там еще тонкостей по виртуализации много всяких. А стандартные элементы — шлак.
Бред. Выводил в таблицу сотни тысяч записей с виртуализацией и подгрузкой при скроллинге на стандартных контролах — все летает.

А вы пробовали делать «резиновый» интерфейс в WinForms (автоматически растягивающийся а-ля Qt Layout и WPF Grid)? Вот это костыли так костыли, и тормоза так тормоза.
Что же сразу бред то. Пробовали и виртуализацию, и отключение антиалайзинга и прочих приблуд. На нормальном компе с нормальной видеокартой все хорошо работает. На нетбуках и простеньких офисных компах тормоза. Я не могу клиенту вывести messagbox на экран — «У вас старый комп, купите новый» :).
Скорее всего связано с тем, что на этих компах включается софтверный режим прорисовки. А на нормальных — рисуется хардварно, через видеокарту.
Успешно гоняли WPF на кассовых терминалах (см. iiko.ru), не надо тут.: р
Статика работает сносно. А там где надо крутить списки и т.п. интерфейс начинает лагать и даже мерцать.
Если мерцает — значит постарался программист. WPF рисует картинки одну за другой, не закрашивая окно каким-то цветом в «межкадровых» переходах.
Судя по вашим ответам, виртуализация у вас не работала. Иначе 2000 записей тут не причем, должно было также тормозить и на 20 записях. А в причине вы не разобрались.
Не буду сильно спорить о жизненной необходимости выводить в таблицу такое количество строк, но опыт показывает что пользователям часто и 50 за глаза хватает, чтобы запутаться. Мы стараемся двигаться в сторону упрощений средств фильтрации выводимых данных. 2000 — это все-таки слишком много для одного человека. В результате он все равно выполнит с таблицей какую-то сортировку, введет фильтр и найдет нужную ему строку, так почему бы не разработать удобные средства фильтрации строк до вывода в таблицу. Виртуализация и постраничная навигация — тоже выход.
Кроме того с таблицами на WPF есть одна тонкость — их ни в коем случае нельзя размещать в резиновых контейнерах, потому что в этом случае виртуализация не работает — таблица сразу же показывается в полном размере, несмотря на то, что 95% строк выходят за пределы экрана.
В .NET 4.0 добавили и в .NET 4.5 немного исправили виртуализацию с пиксельным скроллингом и элементами разных размеров. Не особо пользуюсь гридами (считаю их адским порождением энтерпрайзового говнософта), но работать должно. :)
Я к тому и веду, что 2К строк — это адски много, а для 10-50 строк можно придумать и более наглядное представление, чем таблица
Только конечным пользователям это очень сложно объяснить. По опыту общения, людям проще (быстро) получить 100К строк, а потом накладывать на них фильтры, чтобы найти те 20 нужных
Да поди с выходом Windows 8 и приложений для него подтянут XAML. Хотя отсутствие сильной конкуренции все же сказывается.
Дык впихали же в это метро очередной огрызочный недо-WPF. То есть мало того, что XAML, так ещё и урезанный со всех сторон. И, похоже, ничего улучшать не собираются, ибо вариантов нет.
Всё же в вин8 используется пересервелат, а его писала другая команда, слабо связаная с WPF. Да, нехватает пары встроенных фич (RelativeSource, DataTriggers, etc), но дискомфорта не испытываю.
XAML это конечно адовое угробище, что уж тут уж.
XAML тот еще ужас, но для своего времени идея была весьма хороша. Особенно круто было поняв, что кроме накидывания формочек в Delphi/другом подобном конструкторе есть и другие методы построения интерфейса, перейти к написанию интерфейса десктопного приложения через разметку. Жалко только, что тамошние красоты безбожно едят\ели(три года как не пользовался) ресурсы машины (
Ну, представленные заголовки XAML и HTML-страницы совершенно не идентичны по функциональности. Как-то неправильно их сравнивать.
Странно, что автор не сравнивает сам код HTML с XAML. HTML — это ужас и ад, набор кучи грязных хаков, головная боль с поддерживаемостью кучи браузеров, нетипизированный и примитивный javascript и пр. После HTML писать код на XAML — сплошное удовольствие.
Я так понимаю автор хотел показать не то, что ASP.NET выглядит лучше чем WPF, а то, что ASP.NET 2012(13)-го года выглядит лучше чем ASP.NET 2006-го года. А WPF как был так и остался.

А так согласен. Я с бОльшим удовльствием набиваю руками «горомоздкий» XAML, чем «развивающийся» HTML хотя бы и приправленный knockout-ом.
Я хоть и ASP.NET разработчик, но должен отметить что несколько странно сравнивает. Т.е. за это время ASP.NET наряду с медленным развитием WebForms (от которых автор отмахивается) получил еще (согласен что крутой) MVC. Но это 2 ветки в рамках одного ASP.NET. Тот же код страницы — Razor это не новая версия ASPX, это отдельный рендер.

Опять же, даже если считать XAML избыточным, то не надо забывать что в HTML+CSS это компенсируется пачкой хаков для разных браузеров.
> После HTML писать код на XAML — сплошное удовольствие.

Для меня после embedded разработки на C писать на C# + XAML вообще удовольствие. Признаться честно, я сегодня впервые узнал, что есть негатив про WPF :)
> Больше всего огорчает то, что нет альтернативы. В мире Веба ASP.NET конкурирует с Ruby и PHP — если не нравится один, то можно выбрать другой. На Windows десктопе я по сути прикован к WPF.

Так откройте для себя JavaServer Faces (JSF), наконец!
Для веба я его открыл и закрыл. Столько неявных косяков и вынужденных условностей… Одно отсутствие поддержки GET чего стоит. Или странная событийная модель (подробности уже не помню) когда вроде обработка ошибок запускается несколько раз подряд в разных слоях из-за чего нужно вводить довольно таки странную логику.
> Одно отсутствие поддержки GET чего стоит.

Посмотрите современную версию JSF 2.0.
Какая же она современная, если вышла пять лет назад и имеет проблемы с новыми технологиями вроде HTML5? И собственно про нее я речь и веду, есть несколько хитростей и трюков связанных с доступом к переменным из GET, но полноценной поддержки GET в этой версии нет.

Сам по себе проект компонентного веб-фреймворка интересен. Но собственные неприятные заморочки устаревшего JSF 2.0 убивают всю радость от его магии.

Если хотите подробностей, прочитайте jdevelopment.nl/jsf-22/ там и про GET тема раскрыта и про другие вкусности, которых очень сильно не хватает старенькому JSF 2.0
Спасибо за ссылку. Но чем вызвана ваша нужда в полноценной поддержке GET. Что в нём такого ценного, что невозможно сделать средствами POST-запроса?
Передать ссылку, которая будет совершать некое действие в компонентном фрейворке, напирмер.
>> На Windows десктопе я по сути прикован к WPF.
> Так откройте для себя JavaServer Faces (JSF), наконец!

Для десктопа? Это разве не web application framework?

Но даже если есть порт для десктопа, то вот так вот взять, все кинуть и начать переписать все проекты на Java? :)
> Для десктопа? Это разве не web application framework?

В том числе. Ведь существует класс настольных приложений, работающих по модели клиент-серверных взаимодействий не только в сети, но и в рамках отдельной машины. Никто не мешает запустить локально сервер приложения JSF в составе, скажем, контейнера сервлетов Apache Tomcat или Jetty, запущенного в виде системной службы. А клиентская часть будет работать с ним как с обычным REST-сервером, гибко разделяя полномочия доступа к данным. Отрисовка форм и элементов виджетов выполняется в рамках концепции AJAX любым современным web-engine.
Скажем так, это возможно только для очень узкого круга задач. И рекомендовать такой подход как замену WPF, мягко говоря, странно.
откройте для себя play2, это гораздо лучше любого jsf )
более неудачную технологию придумать было сложно
По переводу: может кто-нибудь объяснить зачем «bind» и его формы был не переведен, а записан русскими буквами — «байнд»?
Есть же (вроде) общепринятый технический аналог «привязка».

Это особенность данного перевода или так принято переводить или «байнд» — общеупотребительное слово?
Никогда в жизни не слышал слово «привязка». :) Я русских переводов не читаю, и в особенности обхожу стороной русский MSDN, будет он неладен. Одно знаю: если бы в тексте были слова типа «привязка», то я долго бы чесал репу над тем, что имелось в виду.
UFO just landed and posted this here
Как бы там ни было, но на сегодня WPF+MVVM является единственным вменяемым инструментом для C# разработчиков, которые занимаются десктоп разработкой под Windows. Сам перешёл на эту технологию с WinForms, и ни капельки об этом не пожалел.
Вся проблема в том что десктоп уходит в какую-то нишевую область.
Уходит ли? Откуда информация? Числа хочу.

Да, про мобилки-планшетики куча шума, но среда бесплатных игр с анальным донатом и приложений за $0.99 меня ну ни разу не вдохновляет.
Цифры? Да сколько угодно, в этом году планшеты обойдут десктопы по продажам, есть еще смартфоны которых просто армия. Миллионы вырученных денег с апстора и гугл плея. Не оправдавшиеся прогнозы на продажи десктопа с выходом w8. w8 не спасла ситуацию. Появление устройств, которым десктоп не нужен, те же фотоапараты с андроидом на борту. Они сливают фотографии на прямую, вам не нужен больше ноутбук что бы слить фотографии. Кабели для планшетов. Помоему очевидно, что пк из клиентской машины превращается в продукт нишевый. Пусть нишь пока что много. Разработчики, дизайнеры, офисный планктон( да и тут google docs и майкрософтовское подражание гугл доксу наступают). Дошло до того что в своей новой системе из гуевых програм я поставил только скайп. Все остальное ( gimp, браузер, видео плеер, просмотрщик фотографий) системные. В итоге имеем а) сокращение продаж десктопов б) уход приложений в веб. В итоге десктоп остается для узкоспециализированных про задач. Бытовой пользователь( а в месте с ним и массовость) уйдут с десктопа по прогнозам в районе 2015-2017. Я живу в Таиланде. Страна не такая уж и бедная. Сравнима с регионами России. Тут у многих планшет единственное «большое» устройство. Фоточки, видео, музыка, игрушки — все там. Я спросил у девушки хочешь ноут куплю, она спросила «зачем, купи мне новый айпед, а то мой старый».
десктоп пока нужен, чтобы забэкапить данные с планшета )
А работа куда уйдет? Для развлечений, понятно, что клавиатура не нужна. И сейчас это большой рынок — у людей было мало развлечений, теперь надо их предоставить.
Но с другой стороны всё больше и больше видов работ уходят в работу с компьютером. И даже думаю, что взрыв этого перехода впереди, в недалеком будущем.

Конечно, это не значит, что будет десктоп, что файлики будут у себя держать и т.д. Сотрется по видимому разница между десктопом и вебом. Исчезнет понятие файла, как чего-то, лежащего на физическом устройстве.
И вот как раз интересны технологии, которые эту разницу в разработке стирают. WPF — одна из первых. Не факт, конечно, что она закрепится. (но Майкрософт — нехилая компания, вероятность ненулевая)
А планшетами и телефонами школота пусть играется. Пока нет полноценного искусственного интеллекта, без клавиатуры не обойтись.
Почему искусственный интеллект? Достаточно интерфейса мозг-компьютер, и работы в этом направлении ведутся довольно активно.
О_о
Вы так умеете управлять своими мыслями?

Я подразумевал ИИ, как, например, возможность нормального голосового общения. Т.е. возможно, тогда можно будет программировать — давая советы. Набирать текст — надиктовывая. Вообще, тяжело представить себе работу без клавиатуры, но может быть сильно снизится ее необходимость
Неправда! WinForms — прекрасная тула для разработки декстопного ПО. Использую уже лет этак 10, полет нормальный, ни в чем не нуждаюсь.
WinForms — замечательный инструмент, пока логика приложения укладывается в стандартные контролы. А как начинаются пожелания «хочу элемент списка с двумя чекбоксами, тремя надписями с переносом текста и иконкой» — пиши пропало. В WPF это реализуется простым шаблоном в пять-десять строчек, в WinForms нужно городить кастомный контрол с нечитаемой логикой рендеринга. Следствие — всё запихивается в вездесущие гриды.
Как-то странно сравнивать десктопную WPF и вебовскую ASP.NET.
Подавляющая часть приложений пишется в веб, логично что развитие идёт в эту сторону.
Что мне сразу понравилось в идее WPF (и Silverlight), так это висевшая в воздухе мысль: никакой отдельной разработки под Веб и под десктоп быть не должно. Есть ГУИ — должно быть совершенно не важно, где файл находится и как запускается. Очень не хотелось и не хочется работать на аспнет, писать много чего не относящегося к задаче и при этом, чтобы это был какой-то сайт, а на десктоп надо писать другой код.

Будущее видимо за тем, что разница исчезнет. А может и браузеры исчезнут. И WPF изначально как бы для этого продумывался. Как тогда казалось. Жаль, что сдвигов так и не произошло. И скорее веб придет в десктоп.
У нас в компании сторонники var до сих пор дерутся с любителями длинных строчек кода — далеко не все приветствуют синтаксический сахар и неявные пространства имен. У нас есть сторонники точки зрения, что каждая строка кода обязана содержать полнейшую биографию каждого типа и каждой переменной, начиная с корневого неймспейса. Был один адепт венгерской нотации, который ко всем прочему обращался к каждому члену класса через this.
Лично мне нравятся улучшения, ведущие к упрощению деклараций, но противников такой эволюции тоже хватает.
Все описанные вами предложения по улучшению полностью поддерживаю, особенно понравилось об импортах неймспейсов на уровне проекта.
Венгерская нотация рулит, если объекты слабо типизированы, и компилятор со средой разработки не всегда могут выявить ошибки на стадии компиляции. То есть в C# использование венгурской нотации в условиях существования R# считаю атавизмом (хотя если dynamic использовать, то другой вопрос; впрочем, сам префиксом "_" для приватных членов не брезгую, как и сами мелкомягкие), а вот в XAML повсюду расставляю префиксы, хотя это и не соответствует «официальным рекомендациям».
Ну, скажем так, код изобиловал переменными вида bResult, iCount, а переменная, содержащая любой тип не из примитивных выглядел как oException, например. О dynamic речи не идет — это понятно, что к таким случаям другой подход.
Префикс "_" и обязательное указание private для всех приватных членов класса я тоже использую. Даже написал Extension для студии, который одним нажатием кнопки приводит код текущего класса к удобному мне виду. Он раскидывает поля, свойства, методы, конструкторы, вложенные типы и т.д. по регионам, сортирует все по имени, добавляет private к членам, не имеющим модификатора.
Но в остальном к синтаксическому сахару отношусь вполне лояльно. И var по рекомендации решарпера, и новые async очень нравятся и др.
Огромное спасибо за статью, действительно очень интересно — до сих пор не слышал, что венгерских нотаций на самом деле несколько. Однозначно в первоначальном ее варианте есть смысл, почитаю внимательно на досуге.
Не за что. У Спольски вообще много интересных статей. Если не читали, рекомендую ознакомится. Я, когда в первый раз на них набрел, прочитал всё запоем.
Спасибо за статью. Но не увидел ничего полезного. Пытаться спрятать логику поиска ошибок в имена, а не ограничивать типами — не очень хороший путь.

Вредность исключений — тоже тупик. У Спольски видимо очень императивно мозг работает в силу привычки и он не может доверять исключениям. Его в ступор вгоняет код:
dosomething();
cleanup();

Он сразу цепляется глазами, что за чем-то идет следующее действие. А исключения не гарантируют. Когда мой мозг когда видит последовательность действий, чаще всего говорит: значит последовательность действий не важна, можно менять местами. Если последовательность действий важна, то причисляется в говнокод. Ну по крайней мере попахивает. А если cleanup(); нужен обязательно, я не раздумывая finally пишу.

Опасная строка, не опасная — с какой это вдруг ерунды описывать это в названии. Пусть компилятор проверяет. Нужно типами определять. Да и там есть примечания.

А так, статья интересная. Все таки не слышал о семантическом смысле, а только о типах.

Писал недавно на языке, где нет исключений. О_о. Функции разрастаются до неприличных пределов. Сплошные проверки и ветвления. Кода намного больше, чем полезного
А-а-а, сразу с ужасом вспоминаю WinAPI с его бесконечными префиксами LPCTSTR, «обратно-совместимыми» WPARAM/LPARAM и прочими кошмарами. %)

Во-моему, несправедливо записывать async в синтаксический сахар, учитывая, сколько логики он за собой скрывает. :)
Да, но бывают субъекты, считающие синтаксическим сахаром любые нововведения, позволяющие писать то же, что и раньше, но меньшим количеством кода.
А чем вас this не устраивает? По мне так, улучшает читаемость.
Это религиозный вопрос, на него нет однозначного ответа. :)
Согласен что вопрос религиозный. К счастью для меня во всей компании был всего один приверженец данного стиля, и того уволили за профнепригодность. This к увольнению прямого отношения не имело :)
Что до моего личного отношения к этому стилю — когда я вижу страницу кода, на 20 процентов заполненную одним и тем же ключевым словом this — у меня рябит в глазах. Лично я считаю это избыточным, и использую ключевое слово там, где необходимо по синтаксису, либо если нужно быстро найти нужное поле в малознакомом классе. Т.е. использую только на этапе написания кода, а не для того, чтобы оно улучшало читаемость.
Ну тут как говорится — заставь дурака богу молиться. У меня была похожая ситуация с одним сотрудником — студентом. С дуру показал ему как я оформляю исходники, ему очень понравились регионы. А у меня еще есть набор сниппетов для объявления DependencyProperty, в котором каждое свойство — статическое поле и «backing property» обернуты в регион. Но он малость не заметил, что у меня используется строгая группировка по типу элемента (поле, метод, свойство) и по семантике в группах больших размеров. Так в итоге его код выглядит как поток бредового создания из 100500 регионов и семантикой разбросанной как попало. В регионах всё, каждое свойство, каждый метод с своём регионе, иногда попадается несколько регионов на один метод. Т.к. я потребовал от него, что бы он писал комментарии, как минимум XML-описания к интерфейсной части своих экспортируемых классов — весь код загажен тонной бессмысленного текста в духе «а вот тут мы присваиваем i значение 4». В итоге в написанном уже не мог разобраться никто, начиная с самого автора. Не знаю где он сейчас работает, но горе той компании.
Да, избыточное комментирование тоже присутствовало, 90% членов класса имело Summary, имеющее вид типа Метод + перевод названия метода на русский язык, и внутри методов Капитан Очевидность потоптался изрядно.
Я пару лет назад почти отказался от группировки членов класса в регион по функционалу (типа #region Init).
Я проанализировал пользу от них и сравнил с трудоемкостью поддержания регионов в актуальном состоянии.
И понял, что при коллективной разработке в тематические регионы постоянно заползают чужие методы, все это путается и навигация по коду страдает.
Сейчас пришел к отдельным регионам по типу члена класса (поле, свойство, метод, конструктор, вложенный класс и т.д.). Внутри каждого региона идет сортировка по модификатору, потом по имени члена. С автоматическим стилизатором я сейчас вообще не заморачиваюсь при написании кода — бросаю члены класса где попало, главное — правильное именование, чтобы сортировка давала плоды. Закончил редактировать класс — нажал кнопку стилизатора, он все разбросал по местам и порядок. Меня устраивает и никто из наших не жалуется.
Самым большим злом считаю регионы внутри метода, которых у того паренька тоже хватало. Если методу вдруг понадобились регионы, то это уже не ООП получается, а какое-то функциональное программирование, попахивает неправильной архитектурой и метод нужно дробить.
Я вот не представляю, где this может мешать.
Если метод изменяет какие-то приватные члены, то это должно быть видно сразу, а не путем прочтения всего класса и тыканья на F12 периодически.
Я считаю this крайне полезным. Во-первых, удобнее выбирать переменную класса. Во-вторых, сразу видно такие обращения за счет цветового выделения. В-третьих, упомянул выше про влияние внутри класса.
Также, считаю важным приписывать base при вызове методов базовых классов.
Если есть способ сообщить какую-то полезную доп.информацию читателю кода без лишнего геморроя, то надо ей пользоваться. У читателя быстрее выстроится в голове структура написанного.

p.s. Все выше написанное не про венгерскую нотацию. Тут, конечно, либо одно, либо другое.
Еще раз — удобство this — это вопрос религиозный, и настолько обе стороны нетерпимы, что лучше в одном коллективе не сводить сторонников разного стиля. Лично когда я вижу в одной строке 10 this (вызывается инициализатор, в который передаются 10 членов текущего класса), то «мне хочется схватиться за пистолет» (с).

Родной MSDN приводит следующие варианты использования:
— Для квалификации элементов, скрытых одинаковыми именами
— Для передачи другим методам объекта в качестве параметра
— Для объявления индексаторов
И нигде на MSDN я не видел примеров, в которых this используется для обращения к каждому члену класса. Та самая статья тому пример. This используется только при необходимости, а к полю salary обращаются без посредников.

Совсем не понял насчет base — так ведь недолго и переопределенный виртуальный метод проигнорировать, вызвав метод базового класса, не вижу в чем здесь польза.
Помимо MSDN есть MSDN Blog, где публиковались «Internal Coding Guidelines», коих я придерживаюсь. Там есть следующие рекомендации:
Do not use Hungarian notation
Do not use a prefix for member variables (_, m_, s_, etc.). If you want to distinguish between local and member variables you should use “this.” in C# and “Me.” in VB.NET.

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

p.s. И да, я знаю, что это лишь рекомендации MS для MS, но это уже вопрос религии, как вы писали выше, использовать или не использовать. Как по мне, если разработчики языка придерживаются неких правил, то не плохо бы их перенять.

Этим рекомендациям сами Мелкомягкие не следуют, у них в коде фреймворка почти всегда приватные члены с префиксом "_". Так что рекомендации рекомендациями, но даже в МС понимают, что "_" удобнее, чем "this.". И вообще там куча рекомендаций, на которые МС активно кладёт. Не вижу никакого смысла религиозно следовать документу, который оторван от реальности. (Да, там почти всё — дельные советы, но есть и исключения.)
Некоторые внутри MS возможно и не следуют, а некоторые следуют. Я бы сказал, большинство следуют, но это по личным ощущениям из их блогов. В примерах на MSDN'е венгерка и _ крайне редки, как, впрочем, и в блогах на Codeplex'е и Stackoverflow'е.
Я не про код из документации, а про код фреймворка. Префиксы "_" там повсюду. И в случае WPF ещё и говнокод повсюду, но речь сейчас не об этом. :)
Это тот самый гайдлайн, в которым первым пунктом идет требование использовать 4 пробела в качестве отступа? У нас в компании того, у кого в настройках стоит 4 пробела в принудительном порядке заставляют приводить код к табуляции. Отступы пробелами — это каменный век. Последние лет 6 у меня в настройках студии установлена настройка 1 Tab = 1 пробел, и когда открывается класс, поредактированый с пробелами, у меня на экране разброд и шатание — методы пляшут по экрану.
Из-за этих внутренних гайдлайнов Visual Studio до сих пор во всем автоматически сгенерированном коде (дизайнере, например) игнорирует настройки и генерячит код с отступами в виде пробелов.
Очевидно, что тот гайдлайн — для компании с очень длинной историей и огромным количеством старого кода. Консерватизм это почти всегда не очень хорошо, о чем и речь в данном топике.
Тут кому как удобнее (религиозно). Как по мне, если код нормально написан, то там не так много отступов и тогда 4 пробела даже читабельнее, чем 1. Один пробел, наверное, удобнее, если есть множественные вложенные условия, тут думаю явно попахивает необходимостью рефакторинга.

p.s. Про табы согласен, да они лучше.
Табы — это из времён экономии на байтах (таб — на три байта меньше!) и ущербных средств разработки (которые не могут при нажати на backspace вернуться на 4 позиции). Часто в достоинства табов записывают возможность каждому разработчику использовать свой любимый размер, и что при этом он никому не будет мешать. Но это — миф, который разбивается о реальность, в которой существуют переносы внутри строки. Чтобы такие перенесённые куски правильно у всех отображались, нужно очень скрупулёзно составлять отступ из смеси табов и пробелов (если нет правила «перенос всегда на один таб больше»). Этим никто в здравом уме и трезвой памяти заниматься не будет.

Итого — у табов ноль достоинств. И куча проблем с генерируемым кодом. И необходимость настраивать отступы во всех редакторах. И необходимость конвертировать отступы после вставки откуда-либо, потому что табы не использует никто.

Не знаю, с чего вы взяли, что пробелы — это каменный век. Вообще-то с точностью до наоборот.
История движется по спирали, сначала (ещё на печатных машинках, позже на телетайпах и терминалах, сейчас в текстовых процессорах и системах вёрстки) табы были шагом вперёд, но там было ключевое отличие — позиции табуляция настраивались вручную типа «1-я табуляция 5-й символ, вторая 17-й, третья — 52-й» и их равномерное расположение было лишь частным случаем. Интерпретация табуляции как фиксированного числа пробелов просто использование инструмента не по назначению.
Студию можно переучить или создать свои базовые шаблоны для файлов.
Если метод изменяет какие-то приватные члены, то это должно быть видно сразу

Префикс _/m_ вам в помощь. По-моему, короче и не менее наглядно. Активно используется самими мелкомягкими в коде фреймворка.

Во-вторых, сразу видно такие обращения за счет цветового выделения.

Настраиваемая подсветка кода решарпером вам в помощь.
Не у всех есть Решарпер, да и не-экспресс студия на работе. А про венгерскую нотацию я написал:
Все выше написанное не про венгерскую нотацию. Тут, конечно, либо одно, либо другое.
Если у меня на работе нет будет решарпера, то я уволюсь, даже минуты не раздумывая. Разница между студией с решарпером и студией без решарпера — такая же, как между студией без решарпера и блокнотом. Цена решарпера — для любой компании смешная. Выгода в качестве кода и скорости его разработки — огромна. В этой компании наверняка ещё и тестировщиков нет — экономия же. :)
Я знаю, у меня есть решарпер, прикупил под Новый Год со скидоном. :-) Но те, кто смотрят мой код или дорабатывают — у них нет решарпера, и даже нет студии версии Pro или выше (на экспресс расширения не ставятся). Компания не чисто софтверная, программный отел не так давно появился, так что пока экономят.
Одна довольно известная софтверная компания с корнями в Питере приглашала к ним на работу. Эйчар кричал про миллиарды долларов, за которые их недавно купили; тимлид — про миллионы долларов, которые приносит проект. На вопрос «используете ли вы решарпер» тимлид скуксившись ответил «ну… мы подумывали об этом… Но это ж надо согласовывать расходы...».
Тот же MSDN указывает два вариант использования base:
— Вызов метода базового класса, который был переопределен другим методом
— Определение конструктора базового класса, который должен вызываться при создании экземпляров производного класса
И, заметьте, больше никаких «на всякий случай». Потому что завтра придет программист, которому понадобится сделать один из методов базового класса виртуальным и переопределить его в наследнике. И он будет головой о стенку биться, не понимая почему breakpoint у него не попадает в override метод. Особенно если класс большой и сложная архитектура.
Так же и this — при правильном подходе к именованию членов класса он не нужен. Все локальные приватные начинаются с _, все public — с большой буквы. Конечный класс должен работать как единый класс, наследник от базового, и так ли важно — где определен член класса — в наследнике или базовом классе? Эта избыточность ни к чему и только усложняет чтение кода.
Про base переборщил, не прав, признаю. Мысль в другое русло случайно ушла. :-)
Про префиксы и this написал выше.
Да, все верно. Работаю с wpf еще с тех пор, когда он назывался Avalon. И проблема описана правильно — нет конкуренции. К тому же, как я понимаю, основные люди, которые стояли за первоначальный идеей, теперь занимаются другим, и в команде wpf не осталось ярких людей, которые могут двигаться продукт (как это происходит с asp mvc).
Есть еще такой факт, год назад команда, которая занимается xaml, было переподчинена из DevDiv в подразделение, которое занимается разработкой Windows.
Возможно, это принесет какие то плоды.
UFO just landed and posted this here
Как раз в asp они есть. Ну, или были до тех пор пока оттуда не ушел Scott Guthrie двигать Azure :)
UFO just landed and posted this here
Конвертеры и Биндинг это то за что я мне нравится WPF, хотя уже года два серьезного на нем ничего не писал.
XAML конечно страшен, но если с ним разобраться — вменяемая вещь. Просто пишешь код компонентами.
Не сказал бы что MVVM это плохо, думаю они с MVC равноценны.
Очень странная позиция автора «длинный код — значит непонятный и сложноподдерживаемый». На Perl'е-то, вишь, можно куда более лаконично писать, чем на Яве, однако какой код проще поддерживать? Некоторые вещи, которые автор называет излишними, на самом деле нужны для удобства и однозначности. Cпрячь неймспейсы — получишь невалидный XML, который нельзя будет разобрать сторонними средствами, и много-много непонятной магии. Убери конвертеры — появится проблема дублирования кода и потребуется написание связующей прослойки для отладчика.

Я согласен, что некоторые вещи можно было бы сделать и поудобнее (ICommand, да, или пресловутый NotifyPropertyChanged), но они все решаемы. С появлением нормального Autocomplete от R#, который моментально подсказывает что угодно вплоть до свойств DataContext'а, все проблемы «длинного синтаксиса» и «избыточности» практически забылись.
На Perl'е-то, вишь, можно куда более лаконично писать, чем на Яве, однако какой код проще поддерживать?

Есть немало народа, который плюётся от «энтерпрайзовости» Джавы (и всего, что вокруг) и воспевает Руби с аналогами, у которых краткость кода стоит не последним приоритетом. :) Я считаю правильным, когда простые вещи делаются просто, а сложные — пропорционально сложно.

Скажите, XAML кто-нибудь разбирает как XML? Это невозможно делать полноценно, потому что половина информации лежит в невалидируемых атрибутах с «лисповыми» markup extension'ами.
Мне видится не менее важным наличие в языке\технологии единообразия, ортогональности и предсказуемости. Субъективно скажу, что как раз C# / WPF для меня стоит ровно на золотой середине между энтерпрайзнутостью Java и лаконичностью и выразительностью Python / Ruby.
Написав немало кода на очень слабо типизированных скриптовых языках, я тоже пришёл к выводу, что хочу чего-то строже. А C# — самый набитый фичами «строго»-типизированный язык. Пожалуй, если бы не необходимость в интеропе, он был бы даже идеален (когда-то писал на плюсах и ржал над пишущими на басиках и дельфях, что им приходится вручную заголовочные файлы переписывать, а теперь сам там оказался :D ).
Я считаю правильным, когда простые вещи делаются просто, а сложные — пропорционально сложно.


Это шикарное замечание.

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

У WPF же (и всех продуктах Microsoft, которые они не копируют из opensource )--steep learning curve. То есть пока вы не прочитаете 1000 страниц книжки, ничего вменяемого (правильно) сделать не сможете. Это значит, что в технологии множество hidden dependencies, высокая связность, она не модульная, не расширяемая (и ASP.NET MVC по всем этим пунктам лучше WPF, потому что скопирован с RoR).
Полностью согласен с тем, что WPF меняется слабо. Добавляются новые фичи, которые хоть и приятны, но не сильно упрнощают жизнь.
Жизнь спасает развитие решарпера, который подсвечивает всё больше, автокомплитит всё лучше, позволяет искать по коду.

У нас разработка построена через MVVM, причем вью модели действительно покрыты тестами. Базовый класс тоже есть, но основная заслуга его в том, что он позволяет писать
UpdateProperty(() => Property,ref property, value)
вместо
if(value != property) { property=value; RaisePropertyChanged("Property"); }
без потери производительности. Куча конвертеров на все случаи жизни объявлены в одном из ResourceDictionary, который один раз подключается и используется.

Не знаю как у авторов текста и перевода, но по большей части ксамл пишется в write only режиме. Наполовину копируктся из накиданного в бленде, наполовину ручками. Создаётся адекватная вью модель со всеми командами и пропертями, после чего для неё пишется XAML, который после рендера отображается как требуется. После про XAML на долгое время забивают. Изменения, если и нужно делать, то, почти всегда, локально. Выглядит это так: найти используемое свойство, решарпером отыскать байндинг в XAML, подправить отображение в окрестности найденного места.

XAML, как и просто разметка html — треш, угар и содомия. Но с подходом — один раз сверстать и дальше чуть чуть править, то жить можно.
Да, спустя 6 лет в шарпе повился CallerMemberNameAttribute, а в решарпере PropertyChangedNotifyAttribute (или как его там)… Лучше поздно, чем никогда. :)
CallerMemberNameAttribute это фича 4.5, на который пока перейти не получается. Но в планах на будущее

Про PropertyChangedNotifyAttribute не понял, либо не знаю. С аттрибутами были разные страшные вещи на PostSharp, но ни к чему хорошему они не приводили.
Если этот атрибут навесить, то Решарпер начинает проверять имена передаваемых свойств, адекватно подхватывать имена при рефакторинге и т.п. Отпадает необходимость в expression'ах — с решарпером строчки становятся полноценными «указателями на свойства».
а поделитесь магией как вы Expression<Func> разворачиваете в if(..) {doSet} без потери производительности?
к сожалению не поделюсь, поскольку код разглашать не могу, но используются различные хитрости с кешированием результата, из-за чего экспрешен используется только один раз.

Нечто похожее написано вот тут:
lambdy.ru/post/9869744363/expression-trees
Столько сложного кода в статье, а изначальная логика странная. :)

реализацию интерфейса INotifyPropertyChanged используют для ViewModel’и в UI-паттерне MVVM (из мира WPF/Silverlight) именно из соображений производительности (вместо использования DependencyProperty и наследования от DependencyObject)

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

Что касается странностей кода, то оптимизации часто порождают необычные конструкции. Главное чтобы они были изолированы и оттестированы.
Советую обратить внимание на мой комментарий выше. Начиная с .NET 4.5 и ReSharper 7.1, необходимости в разборе выражений нет.

А вообще, экспрешены, вроде, пренебрежимо мало просаживают производительность.
Я сейчас крамольную вещь скажу, по-моему это круто, что XAML не меняется! Как работало все несколько лет назад, так и работает.
Что ж не на WinForms-то пишете? Уж они-то вообще не меняются. Или VB6.
Потому что cross-compile Silverlight & WPF
Согласен. Особенно по поводу того, что сделали с XAML в WinRT.
UFO just landed and posted this here
WPF должен был стать мега-революцией, но в процессе случилась революция веб, втч веб-приложений, и большую часть сил, как автор уже заметил, направили на ASP.NET.
У МС так бывает — технологию не убивают, но она уже не в приоритете, и будет медленно умирать.
Насчёт смерти сомневаюсь, всё-таки мелкомягкие сами WPF едят, у них VS на WPF. Я воспринимаю это как обещание не угробить технологию. :) Хотя сервелат вон при смерти, хотя мелкомягкие его сами используют…
ActiveX и COM компонентов МС тоже сделал много. Что не помешало им благополучно умереть.
У них слабосвязанные отделы, так что решение одного использовать технологию не гарантирует ее дальнейшее развитие.
Что, в целом, правильно.
Вообще-то СOM и ActiveX живее всех живых, с чего это вы взяли что они «умерли»?
Пуск -> Визуал Студия -> Тулс -> OLE-COM Object Viewer и посмотрите сколько всякой фигни в вашей системе понаставлено.
Ооо да, всё так.
BoolToVisibilityConverter и IsNotNullConverter

Ага. А еще есть большая библиотека WPFHelpers в которой, как не трудно догадаться, собраны утилиты вроде MyVisualTreeHelper для нормального обхода дерева, с поиском потомков, Binding2 (sic!) который не ест в тихую исключения, происходящие во время передачи значения свойства, KeyGesture2 (sic!), который позволяет указать на что реагировать (нажатие или отпускание клавиши) и как работать с модификаторами (точное соответствие, любая из клавиш), ToolTipHelper, который позволяет генерировать тултип для элемента только на момент показа тултипа. Обычный метод через Binding приводит к немедленному обращению к свойству, содержащему тултип, даже если он не показывается. Что там еще. ClipboardHelper для установки каллбека на смену содержимого буфера обмена. EnumHelper для привязки перечислимых типов к комбо-боксам с переопределением текстов и иконок. DragDropManager, велосипед для нормальной поддержки перетаскивания и фидбеком. Кончено всеми любимый ThemeManager, что бы можно было форсировать визуальную тему приложения, это наверное вообще самый популярный велосипед. ValidationHelper. Пришлось конкретно помучиться что-бы диалог с ошибкой валидации не принимался по кнопке Ok, а ругался вменяемыми словами. Самый жирный класс это ResourceHelper, что бы иконки и текст из ресурсов сборки можно было грузить из кода и через MarkupExtension в котором указывается одно имя ресурса. Кто имел дело с «pack://application:,,,/» тот поймет. Проще застрелиться чем написать правильный путь к иконке.
Т.д. и т.п.

Ну еще немного костылей вроде такого. Что делает этот код?
        public static bool IsEmpty(this FlowDocument fd)
        {
            if (null == fd) return true;
            TextPointer contentStart = fd.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward);
            if (null == contentStart) return true;
            TextPointer contentEnd = fd.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            if (null == contentEnd) return true;

            return new TextRange(contentStart, contentEnd).IsEmpty;
        }
Всего-лишь выясняет, есть что нибудь в документе или нет.
Или вот:
        public static bool GetRelativeMousePosition(this Visual relativeTo, out Point result)
        {
            Win32Point w32Mouse = new Win32Point();
            GetCursorPos(ref w32Mouse);
            bool success = false;
            try
            {
                result = relativeTo.PointFromScreen(new Point(w32Mouse.X, w32Mouse.Y));
                success = true;
            }
            catch (InvalidOperationException)
            {
                // Если элемент не подключен к корню PresentationSource,
                // это обозначает, что мы не в состоянии получить координаты мыши.
                result = new Point(double.NaN, double.NaN);
            }
            return success;
        }
Пришлось нагородить по тому что… сюрприз! InputEventArgs.GetPosition не работает, если происходит операция Drag&Drop, и PointFromScreen работает не во всех сценариях (иногда Vusual еще не подключен к PresentationSource на момент вызова метода).
И таких костылей огромное море.

Да отдельный ад приготовлен для авторов гениальной идеи обработки пользовательского ввода в виртуальных методов. При таком подходе состряпать что-то вроде перетаскиваемой кнопки становится огромной проблемой. Корректная обработка ввода это вообще самая главная проблема.
Так же не забуду про «отличнейшую» реализацию сортировки и группировки. Если вам вдруг захочется сгруппировать данные, а потом еще и отсортировать группы по каким-то правилам то… упс. Приходится писать суперкривые костыли для сравнения исходных элементов.
Да, а еще layout. Arrange, Measure, вроде чего там. Однако всё это безобразие выполняется отложено, и вклинить свой код в процесс расчета положения элементов в нужный момент бывает очень трудно. Этот факт превращает реализацию такой тривиальной операции как прокрутить дерево, что бы был виден указанный узел в самый настоящий ад! Так же первое время постоянно натыкался на то, что некорректно работает TransformToAncestor изнутри методов ArraneOverride/MeasureOverride. Потом уже привык дергать диспетчер. Но работает всё на честном слове. Если вдруг Microsoft поменяет приоритеты в DispatcherOperationPriority, то всё развалится.

Ну и баги, куда ж без них. Помнится я их постил на connect года 3 назад… Но они и ныне там. В память запало — игнорирование переопределенных настроек локали в панели управления, показ контекстного меню, если в нем нет элементов, утечка памяти при использовании WindowsFormsHost. Что-то еще было по мелочи.

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

Короче резюме: продолжаю колоться и плакать.

Ну а по поводу MVVM — я использую паттерн M-V-Poo, как его метко назвал Dr.WPF. Пишу модель данных. Базовых классов нет, юзаю DependencyObject или INotifyPropertyChanged. Потом пишу UserControl который хостит модель и имеет её в качестве DataContext. А дальше смесь TwoWay Binding'ов и обычных OnClick. В них выполняется код, меняющий модель (а она шлет уведомления об изменении своих свойств).
Binding2 (sic!) который не ест в тихую исключения

В смысле, если свойство посередине пути null, то всё нормально, а если свойство бросило исключение — оно вылезет? Как вы этого добились, если не секрет? Я сам проблемы с байндингом обычно ловлю записью в лог всех first chance исключений.

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

У вас в приложениях есть несколько тем?

Этот факт превращает реализацию такой тривиальной операции как прокрутить дерево, что бы был виден указанный узел в самый настоящий ад!

Я вообще не понимаю, кто в здравом уме и трезвой памяти мог выпустить контрол дерева без возможности прокрутки к выбранному элементу и даже без возможности биндиться к выбранному элементу…
Исключения могут происходить при передаче значения свойства изнутри каких-то кишок PropertyPathWorker или как-то так. В общем если сеттер свойства к которому есть байндинг кидает исключение, то байндинг его просто глотает. Binding2 (Ex) работает через UpdateSourceExceptionFilter. Скинул исходник сюда: pastebin.com/T8dzv8eT. Отдельный изврат используется для доступа к BindingExpression.TargetElement, по тому что свойство, по доброй традиции WPF — internal (да, забыл отдельное спасибо выразить и за это). И кроме того пришлось отдельно накатать MarkupExtension что бы можно было BindingEx использовать внутри Setter'ов в стилях. По тому, что если попытаться вставить в стиль голый "{wpfh:BindingEx Path=path}" то всё закончится рантайм исключением при применении стиля к экземпляру контрола. В общем со стилями тоже всё весело. Наворот с кешированием метода-акцессора для того, что бы не обращаться каждый раз к рефлексии.

Визуальных тем несколько в WPF — Luna Normal, Silver, Aero, Royal, и т.д. У меня в приложении жестко зашит код, который включает тему Luna если задетекчена классическая тема, по тому что она (классическая тема) содержит приличное количество ошибок разного калибра в стилях элементов, иногда очень раздражающих (вроде пропадания подсветки выделенных элементов в списке) и на практике слабо применима.

О да, System.Windows.Controls.TreeView заслуживает отдельной статьи о том насколько чудовищен этот контрол.

Так же я долго не мог осознать как это так можно выпустить фреймворк, который не имеет в себе контролов для ввода целых чисел и чисел с плавающей точкой. Т.е. что-то такое можно состряпать из TextBox, IValueConverter и Validation'а, но что бы было удобно и оно вмеяемо реагировало на все издевательства пользователя сил приходится приложить не мало.
Ох, почитал я Ваши злоключения и понял что пока мы с WPF повременим и будем делать толстого клиента на WinForms. Там хоть все понятно и неожиданных багов нет. Одно жаль что кроме старенького SCSF никаких новых фреймворков для разработки приложений под винформы нет, типа того же Prism. :(
Да ладно, всё не так страшно. :) Свои классы биндингов, перекрытие тем и прочее такое возникают после нескольких лет активной разработки, и для первых приложений смысла в этом всём мало. И вы, скорее всего, не упрётесь в откровенные баги — по моему опыту, они выползают в довольно сложных и редких ситуациях. Вы не сможете глубоко уйти в эзотерику в первом приложении, чтобы ощутить это на своей шкуре. Ну да, некоторых вещей будет откровенно не хватать (типа контрола для ввода чисел), но на первых порах можно обойтись и без этого, а как знания окрепнут — допишете к полям ввода валидацию, конвертеры и шаблоны с кнопками. Просто не надо пытаться сделать всё с первой попытки идеально.
>И вы, скорее всего, не упрётесь в откровенные баги

Я вот уперся в баг/фичу с принудительным кэшированием BitmapImage и невозможностью его обнуления человеческими средствами уже в своем первом приложении :) В WPF его однако поправили, тем не менее, он с новой силой вылез в WP8 ;)
Да, Athari всё верно написал. При всех своих детских болезнях WPF даёт фору WindowsForms по многим параметрам. Стилизация, шаблонизация, дата байндинг, привязка к коллекциям, панели, визуальное дерево, маршрутизируемые события, виртуализация — всё это очень мощные инструменты позволяющие существенно уменьшить объем кода и повысить простоту его поддержки.
Порог вхождения выше, но он окупается. В общем если передо мной бы сейчас опять встал выбор — WinForms, WPF, WinRT, или даже Delphi, я бы не задумываясь выбрал WPF.
> Так же не забуду про «отличнейшую» реализацию сортировки и группировки. Если вам вдруг захочется сгруппировать данные, а потом еще и отсортировать группы по каким-то правилам то… упс. Приходится писать суперкривые костыли для сравнения исходных элементов.

Не совсем понял. А как же CollectionViewSource? Как-то не было проблем с группировкой и сортировкой.
Отсортировать — не проблема, всё хорошо, добавляешь набор SortDescription'ов, и всё. А вы попробуйте отсортировать сами группы. Вот пример от майкросовтовца: www.zagstudio.com/blog/362#.UO7LGW8bfp4
Там у него всё хорошо, даже есть фраза что «мы не добавили сортировку групп по тому, что можно отсортировать элементы по тому же свойству, по которому они сгруппированы». Это так, если такое свойство есть, и оно одно, и тип его совместим с IComparable. НО! Есть абстрактный класс — GroupDescription в котором можно сгруппировать элементы по совокупности свойств, т.е. как угодно. В 99% случаев (на моей практике) как раз это и требуется, а конкретно свойства, по которому можно сгруппировать нет!
Т.е. если нужна сортировка групп выхода 2: добавить ненужное свойство группировки, да еще реализовать в его типе логику сравнения, или использовать 2 CollectionView, 2й для свойства Groups первого (ужасное решение по понятным причинам).
И всё это вместо того, что бы просто в SortDescription n-ного уровня передавать не сам исходный элемент, а его группу. Короче гениальное решение, и отмазка тоже — у нас всё хорошо идите лесом.
Кончено всеми любимый ThemeManager, что бы можно было форсировать визуальную тему приложения, это наверное вообще самый популярный велосипед.

О дааа, писал такой. И название точь в точь. :-)
1) Никто XAML не должен писать руками — это работа дизайнера.
+ Новый blend для маркет-разработчиков:
msdn.microsoft.com/en-us/library/windows/apps/jj129478.aspx

2) Нужно прочитать хоть одну хорошую книжку перед стартом работы с wpf и тогда не будет проблем с Binding. Просто многие разработчики не понимают даже что они делают.

3) Не нужно быть фанатиком и если задачу проще выполнить на button клик, так это нужно сделать.
мда… как-то неуютно становится после этой статьи, учитывая, что я сейчас читаю книгу о разработке на wpf 4.0 и xaml ((
Для беспокойства повода нет.
Я думаю стоит считать xaml тупиком в эволюции вин-десктопа. наверное уже все заметили тенденцию к использованию html5 в разработке приложений под вин8. Мне кажется что к этому все и идет только вот сам стак мс к этому пока еще не готов.
Вам когда нибудь приходилось использовать стили css3 и стили в wpf. думаю что да. Где то сверху прозвучало что стили должны быть реализованы дизайнером а не программером, признаюсь вам что мне никогда не приходилось видеть живого дизайнера wpf. Во всех более менее нормальных сдк разработки «толстых клиентов» есть так называемая компонента WebView во вменяемых сдк она часто базируется на вебките, в wpf что то вроде этого есть но очень корявое. Приведу пример у нас есть команда разработчиков под osx и linux и они в одном из проектов использовали подход с WebView где вся граф часть и большой кусок логики были использованы совместно а вот нам бравым c# разработчикам ничего не оставалось как делать все с 0 на wpf. А теперь представте какой во всем этом авантаж с точки зрения затрат и времени реализации.
Насколько я знаю, дизайнер рисует в фотошопе, а с css возится верстальщик. То что в вебе достаточно работы, чтобы верстальщик был отдельной должностью, не честно для css.

В wpf нет таких проблем, и роль верстальщика вполне может выполнить программист.

То что вы для кроссплатформенности использовали вебвью, ещё не говорит о том, что это правильно. Это скорее от безысходности. Если бы не макос, то логичнее было бы использовать тот же qt.
Кроме того, сколь-нибудь сложный интерфейс на разных платформах ДОЛЖЕН выглядеть и вести себя по-разному (так как того ожидает пользователь).

Так что, раз на раз не приходится. Доказательств «тенденции» вы не привели.
Тенденция очень широкое понятие, если мы говорим о хром ос то это будет слияние веба и десктопа. Если говорить про новшества в вин8 то это вменяемая поддержка html5 в сдк. Даже если говорить про gnome3 или QT последних версий мы видим инструменты которые раньше были присуще только вебу это js расширения для первого и надстройка из js/css для второго. Тенденция в стирание граней между десктопом и вебом.

Я с вами не соглашусь в том что под каждой ос программа должна иметь разное поведение в большинстве случаев это не так. Как раз мы и не искали кросс-платформености мы искали скорее кросс-бихейворизма малой кровью в этом и заключается на мой взгляд тенденция.
«Тенденция писать приложения на html под win8», это вчера 2% приложений писали н хтмле, сегодня 10, после завтра все пишут на html. И никаких сказок про хромос.

Что касается «тенденции к кроссбихевиорсти»
То позавчера apple заставил всех следовать гайдлайнам дизайна и поведения, вчера МС, сегодня Гугл написал гайдлайны стиля и поведения приложений для андроида, а завтра выходит убунту фон, а они уже говорят о гайдлайнах. И самое главное, пользователи в рецензиях требуют того, что бы приложение вело себя подобающе платформе. Вот это я понимаю, тенденция.

Да, есть тенденция разделения гуи и кода, которая пошла с веба и развита там хорошо. (кто бы apple о ней рассказал...) поэтому и подходы по достижению того же результата на десктопе похожи.
кросс-бихейворизм
лично меня очень раздражает (за редким исключением). Обычно за ним я вижу желание компании сэкономить на разработке, наплевав на интересы пользователей. Исключения — весьма нишевые продукты, которые целевой аудиторией используются как основной или даже единственный инстрцмент в работе по сценарию «утром запустили — вечером закрыли, окна приложения фокус за день не теряли», А ОС им нужна лишь, грубо говоря, для запуска. чуть ли не автозагрузке. И даже в таких продуктах неплохо бы иметь возможность менять интерфейс на «родной» для данной (или любимой) ОС малой кровью. Потому что кроме ЦА есть те, кто использует его эпизодически.
тенденцию к использованию html5 в разработке приложений под вин8

Это когда пишутся приложения с нечитабельным кодом и дикими костылями?! Я вообще не вижу в этом смысла, ибо это на HTML5 не похоже, проще и лучше C# + XAML изучить, имхо.
Ну это смотря как писать конечно ну и что использовать. Если бы берете например cef и настраиваете под ваши нужды то по продуктивности и качеству вы сможете обогнать wpf с его костылями в виде иерархий стилей, конверторов и нотифайеров которые срабатывают как им захочется.
Ну CEF и WinJS это разные вещи. А вот как HTML5 обходит WPF по конверторам и уведомлениям об изменении не понятно. Расскажете? :)
А этого там просто нет, берете к примеру jade или mustache пишете ваш вид, далее для логики берете coffeescript, данные получаемые из вида передаете непосредственно в ваш бакенд код, в CEF есть все для такого рода «передач». Все это дело прекрасно тестится, одно слово удобно.
Но сейчас, когда я оглядываюсь на проделанный ASP.NET путь, я вижу огромные изменения. От модели Web Forms до модели MVC, от синтаксиса ASPX до Razor — в лагере ASP.NET действительно занимались инновациями.

Ну правильно, там был Скотт Гатри, который все это дело двигал, а в WPF — хрен знает кто.
Fody рулит! С ним я забыл о том, что такое вызов RaisePropertyChanged

Можно репостить "15 лет WPF: что изменилось". Текст можно оставить без изменений :) Только VS2012 -> VS2021 переправить

Sign up to leave a comment.

Articles

Change theme settings