вторник, 16 ноября 2010 г.

CollectionEditor: валидация уникальных элементов

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

Пришлось писать свой.

суббота, 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 (причем, чаще всего в валидаторах, и регексы чаще всего были крайне примитивными)...

четверг, 4 ноября 2010 г.

Автоматический merge файлов во время установки


Судьба столкнула с довольно интересной задачей. Вкратце, её можно сформулировать как оффлайн-синхронизация файлов в процессе установки.

Я бы предпочел такое решение сделать в виде онлайн веб-сайта, но с командиром не поспоришь. Сказал WinForms - будет тебе WinForms. И WiX - заодно!

Речь идет об утилите для переводчиков для перевода ресурсов действующего и развивающегося продукта. Переводчики должны переводить resx-файлы, и пересылать их нам, разработчикам. Поскольку продукт развивается, естественно, что мы им тоже должны посылать свежие версии файлов, с новыми ресурсами. Посылаемые нами файлы скорее всего будут в виде установщиков - так проще всего. А значит, нужно придумать мерж во время установки!

среда, 3 ноября 2010 г.

Рекурсия Linq'ом

Задача рекурсивного обхода встает очень часто. Например, в SharePoint'е, я сталкивался с этим при рекурсивном добавлении пунктов меню и при удалении пунктов меню с флагом IsExternal (про это есть отдельный пост, "Локализация меню SharePoint 2010"); любые деревообразные контролы типа TreeView также частенько этого требуют, ну да и без всяких контролов, любые вложенные объекты рано или поздно требуют рекурсии или аналогичной по смыслу операции.

Раньше как-то не задумывался, что это можно реализовать на 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'а. В этом посте я расскажу, как нам удалось обойти эту проблему и добиться желаемого.

вторник, 19 октября 2010 г.

Microsoft Magic: Локализация стандартного списка Links

Видимо, серия Microsoft Magic скоро станет самой большой серией постов в этом блоге :)

Итак, задача очень распространенная. Есть в шарике стандартный список 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 в любых списках.