PropertyGrid - очень удобная штука. Однако же, встроенные редакторы коллекций то ли недоделаны, то ли просто не предназначены по задумке для расширений. Мне потребовалось реализовать валидацию уникальных элементов коллекции в CollectionEditor, нашел вариант со StackOverflow, однако глючный и, похоже, непроверенный.
Пришлось писать свой.
вторник, 16 ноября 2010 г.
суббота, 13 ноября 2010 г.
Linq-to-Regex
Думал про нестандартные использования Linq (НЕ Linq-to-<источник данных>). В процессе, исходя из логических умозаключений, набрал в гугле фразу "linq-to-regex". Раньше никогда про него не слышал, не знал, не видел, не думал, что оно такое есть...
Но Linq-to-Regex должен был существовать, по следующим причинам:
1. Регулярное выражение, особенно не банальное [A-Za-z0-9]+ - штука довольно сложная для визуального восприятия.
2. Regex'ы - это идеальное вместилище для труднопрогнозируемых ошибок из серии "очепятка". А шарп по своей идеологии категорически не должен такое разрешать.
3. Regex'ы как класс реализованы в C# и .Net отвратительно, совершенно не встроены в язык, поддерживают очень мало полезных фишек... И несмотря на то, что я обожаю перл, и обожаю перловые регексы, и нет, наверное, ни одного скрипта на перле, где бы я их не использовал - несмотря на всё это, за все те 3 года, которые я пишу на C#, я юзал шарповые Regex'ы ну может раз 5-6 (причем, чаще всего в валидаторах, и регексы чаще всего были крайне примитивными)...
Но Linq-to-Regex должен был существовать, по следующим причинам:
1. Регулярное выражение, особенно не банальное [A-Za-z0-9]+ - штука довольно сложная для визуального восприятия.
2. Regex'ы - это идеальное вместилище для труднопрогнозируемых ошибок из серии "очепятка". А шарп по своей идеологии категорически не должен такое разрешать.
3. Regex'ы как класс реализованы в C# и .Net отвратительно, совершенно не встроены в язык, поддерживают очень мало полезных фишек... И несмотря на то, что я обожаю перл, и обожаю перловые регексы, и нет, наверное, ни одного скрипта на перле, где бы я их не использовал - несмотря на всё это, за все те 3 года, которые я пишу на C#, я юзал шарповые Regex'ы ну может раз 5-6 (причем, чаще всего в валидаторах, и регексы чаще всего были крайне примитивными)...
четверг, 4 ноября 2010 г.
Автоматический merge файлов во время установки

Судьба столкнула с довольно интересной задачей. Вкратце, её можно сформулировать как оффлайн-синхронизация файлов в процессе установки.
Я бы предпочел такое решение сделать в виде онлайн веб-сайта, но с командиром не поспоришь. Сказал WinForms - будет тебе WinForms. И WiX - заодно!
Речь идет об утилите для переводчиков для перевода ресурсов действующего и развивающегося продукта. Переводчики должны переводить resx-файлы, и пересылать их нам, разработчикам. Поскольку продукт развивается, естественно, что мы им тоже должны посылать свежие версии файлов, с новыми ресурсами. Посылаемые нами файлы скорее всего будут в виде установщиков - так проще всего. А значит, нужно придумать мерж во время установки!
среда, 3 ноября 2010 г.
Рекурсия Linq'ом
Задача рекурсивного обхода встает очень часто. Например, в SharePoint'е, я сталкивался с этим при рекурсивном добавлении пунктов меню и при удалении пунктов меню с флагом IsExternal (про это есть отдельный пост, "Локализация меню SharePoint 2010"); любые деревообразные контролы типа TreeView также частенько этого требуют, ну да и без всяких контролов, любые вложенные объекты рано или поздно требуют рекурсии или аналогичной по смыслу операции.
Раньше как-то не задумывался, что это можно реализовать на Linq'е. А ведь оказывается, простейший Extension Method эту проблему решает. Например, потребовалось подписать на событие MouseDown все вложенные контролы некой формы, код в таком случае будет выглядеть примерно так:
Раньше как-то не задумывался, что это можно реализовать на Linq'е. А ведь оказывается, простейший Extension Method эту проблему решает. Например, потребовалось подписать на событие MouseDown все вложенные контролы некой формы, код в таком случае будет выглядеть примерно так:
foreach(Control c in this.Controls.WithDescendants(c => c.Controls)) { c.MouseDown += new EventHandler<MouseEventArgs>(Controls_MouseDown); }
понедельник, 25 октября 2010 г.
Производительность LuaInterface
LuaInterface - это лучший, насколько мне известно, LUA wrapper для .Net-а на сегодняшний день. Конечно, нет предела совершенству, но оперировать враппером действительно очень просто, да и возможности завораживают. Кто не читал, очень рекомендую ознакомиться с документацией, доступной на сайте проекта LuaInterface.Однако, с точки зрения производительности, всё далеко не так радужно. В этом посте я приведу замеры производительности и использования памяти для библиотеки LuaInterface.
четверг, 21 октября 2010 г.
SharePoint 2010 Ribbon: как удалять и заменять OOTB кнопки на риббоне
Всё-таки, Ribbon в шарепойнте - штука полезная. К примеру, Content Editor Web Part именно благодаря Ribbon'у выглядит подобно Word'у, и оттого так нравится многим (в том числе и мне). И естественно, что частенько требуется кастомизировать этот самый Ribbon.
Чаще всего задача заключается в добавлении какой-нибудь кнопки для собственного списка. Это делается довольно просто, и описано в MSDN. А вот недавно мы столкнулись с необходимостью удаления трех кнопок из риббона библиотеки документов - "Создать", "Отправить" и "Создать папку". Вместо них планировалось добавить одну собственную кнопку, которая должна была перенаправлять пользователей на страницу, где на основе вводимых данных документ для библиотеки генерировался бы программно.
Однако, стандартный в таких случаях HideCustomAction элемент, несмотря на несколько часов попыток, не помог удалить искомые кнопки из Ribbon'а. В этом посте я расскажу, как нам удалось обойти эту проблему и добиться желаемого.
Чаще всего задача заключается в добавлении какой-нибудь кнопки для собственного списка. Это делается довольно просто, и описано в MSDN. А вот недавно мы столкнулись с необходимостью удаления трех кнопок из риббона библиотеки документов - "Создать", "Отправить" и "Создать папку". Вместо них планировалось добавить одну собственную кнопку, которая должна была перенаправлять пользователей на страницу, где на основе вводимых данных документ для библиотеки генерировался бы программно.
Однако, стандартный в таких случаях HideCustomAction элемент, несмотря на несколько часов попыток, не помог удалить искомые кнопки из Ribbon'а. В этом посте я расскажу, как нам удалось обойти эту проблему и добиться желаемого.
вторник, 19 октября 2010 г.
Microsoft Magic: Локализация стандартного списка Links
Видимо, серия Microsoft Magic скоро станет самой большой серией постов в этом блоге :)
Итак, задача очень распространенная. Есть в шарике стандартный список Links. Если мы хотим создать инстанс этого списка для собственных целей, это делается очень просто, создаем айтем ListInstance, и заполняем его примерно следующим XML-ем:
Ну и дальше, всё это добавляется в фичу и успешно деплоится.
И вот, мне потребовалось контент этого списка локализовать. Ну например, чтобы у америкосов был google.com, а у китайцев - baidu.com. Создаем ресурсный файл, ну и выносим ссылки. Все вроде просто. Но вот тут всплыл вдруг такой эксепшен:
Нерабочий вариант:
Совершенно случайно, обнаружился рабочий вариант. Сравниваем:
No comments :)
P.S. Актуально для полей типа URL в любых списках.
Итак, задача очень распространенная. Есть в шарике стандартный список Links. Если мы хотим создать инстанс этого списка для собственных целей, это делается очень просто, создаем айтем ListInstance, и заполняем его примерно следующим XML-ем:
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <ListInstance Id="" Title="$Resources:core,linksList" OnQuickLaunch="FALSE" TemplateType="103" FeatureId="00bfea71-2062-426c-90bf-714c59600103" Url="PersonalLinks" Description=""> <Data> <Rows> <Row> <Field Name="ID">1</Field> <Field Name='URL'>http://google.ru, Поиск Google</Field> </Row> <Row> <Field Name="ID">2</Field> <Field Name='URL'>http://omlin.blogspot.com, Блог Омлина :)</Field> </Row> </Rows> </Data> </ListInstance> </Elements>
Ну и дальше, всё это добавляется в фичу и успешно деплоится.
И вот, мне потребовалось контент этого списка локализовать. Ну например, чтобы у америкосов был google.com, а у китайцев - baidu.com. Создаем ресурсный файл, ну и выносим ссылки. Все вроде просто. Но вот тут всплыл вдруг такой эксепшен:
Недопустимый URL-адрес: $Resources: TestResources. >> в Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionListInstances(SPFeaturePropertyCollection props, SPSite site, SPWeb web, Boolean fForce)
Нерабочий вариант:
<Row> <Field Name="ID">1</Field> <Field Name='URL'>$Resources: TestResources, Links_ItemUrl1</Field> </Row>
Совершенно случайно, обнаружился рабочий вариант. Сравниваем:
<Row> <Field Name="ID">1</Field> <Field Name='URL'>$Resources:TestResources, Links_ItemUrl1</Field> </Row>
No comments :)
P.S. Актуально для полей типа URL в любых списках.
Подписаться на:
Сообщения (Atom)
