<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C08FRn08fSp7ImA9WhVbFEk.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072</id><updated>2012-05-31T09:23:37.375+04:00</updated><category term="SOLID" /><category term="быстродействие" /><category term="WSS3" /><category term="flash" /><category term="SMS" /><category term="PropertyGrid" /><category term="XSLT" /><category term="SharePoint2010" /><category term="IoC" /><category term="WIX" /><category term="игры" /><category term="Qumo Libro" /><category term="SPList" /><category term="SPField" /><category term="SharePoint" /><category term="Sandcastle" /><category term="Workflow" /><category term="SPS2010" /><category term="документация" /><category term="Ajax" /><category term="Ribbon" /><category term="Client Object Model" /><category term="Setup" /><category term="лицензионное ПО" /><category term="MEF" /><category term="MAML" /><category term="кодогенерация" /><category term="локализация" /><category term="Linq" /><category term="EcmaScript" /><category term="Scrum" /><category term="блог" /><category term="SPF2010" /><category term="Microsoft Magic" /><category term="MOSS2007" /><category term="JavaScript" /><category term="SSIS" /><category term="Buzz" /><category term="LUA" /><category term="SharePoint2007" /><category term="Visual Studio Express" /><category term="HTML5" /><title>SharePoint для профессионалов</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://omlin.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>71</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/omlin" /><feedburner:info uri="omlin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>omlin</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;DkcERX45eyp7ImA9WhVbE0g.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-1082574766710315712</id><published>2012-05-30T09:00:00.000+04:00</published><updated>2012-05-30T09:00:04.023+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-30T09:00:04.023+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Реализация паттерна UniqueURLs в SharePoint</title><content type="html">На своем докладе на MsDevCon’12 я рассказывал о нескольких паттернах, и в частности — о паттерне &lt;a href="http://ajaxpatterns.org/Unique_URLs"&gt;Unique URLs&lt;/a&gt;. Также, я показывал, как этот паттерн работает на реальном примере – созданном мной Ajax-дашбоарде. Этот паттерн крайне актуален для Ajax-приложений, и строится вокруг следующего утверждения:&lt;br /&gt;
&lt;blockquote&gt;
&lt;div align="center"&gt;
&lt;i&gt;&lt;span style="font-size: medium;"&gt;У каждого состояния страницы должен быть уникальный адрес&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;/blockquote&gt;
Это означает, что когда вы нажимаете на некой странице на кнопку или ссылку, и состояние (внешний вид) страницы меняется (неважно, был ли это postback или callback) — то у этой страницы должен измениться и адрес (т.е. текст в строке браузера):&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh3.ggpht.com/-qJdyR6nEHVg/T8OnlfFeIpI/AAAAAAAABXc/pCIBQYZgWno/s1600-h/image%25255B12%25255D.png"&gt;&lt;img alt="image" border="0" height="226" src="http://lh6.ggpht.com/-NJz5SanQzKg/T8OnmBWetOI/AAAAAAAABXg/KwGYBWb1vXI/image_thumb%25255B8%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="263" /&gt;&lt;/a&gt;&lt;br /&gt;
Если каждый раз адрес менять не получается (например, в случае карт), то нужно предусмотреть кнопку «Получить ссылку» или что-то в этом духе.&lt;br /&gt;
&lt;br /&gt;
Естественно, что если другой пользователь, или этот же, но позже — переходит по ранее запомненному уникальному адресу, то состояние страницы должно восстановиться:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh6.ggpht.com/-TzFkLUX1YaI/T8Op5OpiwBI/AAAAAAAABXk/5y5hIFoajQk/s1600-h/image%25255B9%25255D.png"&gt;&lt;img alt="image" border="0" height="167" src="http://lh5.ggpht.com/-jkQx6YN25OE/T8Op5zg2fhI/AAAAAAAABXo/nPN0Tka8OgA/image_thumb%25255B5%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="280" /&gt;&lt;/a&gt;&lt;br /&gt;
Надеюсь, задача понятна, а теперь давайте рассмотрим реализацию, и некоторые тонкости при реализации этого паттерна в SharePoint.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
На самом деле, как это всегда и бывает, способов реализации довольно много. Например, вы можете написать всё с нуля, или подсмотреть код на каком-нибудь сайте в интернете, или использовать одну из множества библиотек для реализации этого паттерна.&lt;br /&gt;
&lt;br /&gt;
Я стараюсь при возможности ничего не подключать дополнительного и писать как можно меньше кастомного кода (потому что его потом еще поддерживать), в общем стараюсь по максимуму использовать то, что уже есть в SharePoint.&lt;br /&gt;
&lt;br /&gt;
В частности, в SharePoint «из коробки» уже подключена библиотека ASP.Net Ajax версии 3.5, и оказывается, в этой библиотеке есть встроенные средства для реализации якорной навигации, что нам вполне подходит. На MSDN есть статья &lt;a href="http://msdn.microsoft.com/en-us/library/cc488538(VS.90).aspx"&gt;Managing Browser History Using Client Script&lt;/a&gt;, которая объясняет, как работать с якорной навигацией с помощью ASP.Net Ajax.&lt;br /&gt;
&lt;br /&gt;
Если вкратце, потребуется всего два метода:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;При изменении состояния страницы необходимо менять текущий адрес и добавлять соответствующий переход в историю браузера. Это делает метод &lt;a href="http://msdn.microsoft.com/en-us/library/cc488025(VS.90).aspx"&gt;Sys.Application.addHistoryPoint&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;При изначальном заходе на страницу, нам нужно проанализировать текущий адрес и восстановить сохраненное в анкоре состояние страницы. Для этого необходимо подписаться на событие &lt;a href="http://msdn.microsoft.com/en-us/library/cc488024(VS.90).aspx"&gt;Sys.Application.navigate&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
Но при корректном использовании этой связки двух методов, в SharePoint’е всплывает небольшая проблема... А именно, перестает работать переключение локализации «на лету». Возможно, также перестают работать и какие-то другие функции – точно не знаю. Немного покопавшись в отладчике, я выяснил, что проблема зарылась в функции OnSelectionChange:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;OnSelectionChange(value) {
    &lt;span style="color: blue;"&gt;var &lt;/span&gt;today = &lt;span style="color: blue;"&gt;new &lt;/span&gt;Date();
    &lt;span style="color: blue;"&gt;var &lt;/span&gt;oneYear = &lt;span style="color: blue;"&gt;new &lt;/span&gt;Date(today.getTime() + 365 * 24 * 60 * 60 * 1000);
    &lt;span style="color: blue;"&gt;var &lt;/span&gt;url = window.location.href;
    document.cookie = &lt;span style="color: maroon;"&gt;"lcid=" &lt;/span&gt;+ value + &lt;span style="color: maroon;"&gt;";path=/;expires=" &lt;/span&gt;+ oneYear.toGMTString();
    window.location.href = url;
}&lt;/pre&gt;
&lt;br /&gt;
Здесь присваивание &lt;span style="background-color: #cccccc; font-family: &amp;quot;Consolas&amp;quot;;"&gt;window.location.href = url;&lt;/span&gt; должно по идее вызывать перезагрузку страницы, но т.к. на конце url при использовании анкорной навигации идет символ решетка (“#”) и параметры, идентифицирующие текущее состояние страницы (например, “http://site/page.aspx#state=10”), то перезагрузки страницы не происходит, т.к. браузер думает, что мы хотим перейти на анкор внутри текущей страницы.&lt;br /&gt;
&lt;br /&gt;
Довольно забавный баг, но неприятный. Вышеозначенная функция “OnSelectionChange” генерируется прямо в код страницы, непосредственно перед кодом риббона. Редиску, которая генерирует эту функцию, я вычислять не стал. Вместо этого, просто исправил в ней ошибку и теперь переопределяю её после начальной загрузки страницы.&lt;br /&gt;
&lt;br /&gt;
В конечном итоге, класс, ответственный за реализацию Unique URLs в моем проекте, выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: darkgreen;"&gt;/// &amp;lt;reference path="GridController.js" /&amp;gt;
&lt;/span&gt;DW.TasksDashboard._UniqueURLs = &lt;span style="color: blue;"&gt;function &lt;/span&gt;() {

    DW.TasksDashboard.DataLoadManager.add_dataLoaded(onDataLoaded);

    &lt;span style="color: blue;"&gt;this&lt;/span&gt;.FixOnFlyLocalization = &lt;span style="color: blue;"&gt;function &lt;/span&gt;() {
        window.OnSelectionChange = &lt;span style="color: blue;"&gt;function &lt;/span&gt;(value) {
            &lt;span style="color: blue;"&gt;var &lt;/span&gt;today = &lt;span style="color: blue;"&gt;new &lt;/span&gt;Date();
            &lt;span style="color: blue;"&gt;var &lt;/span&gt;oneYear = &lt;span style="color: blue;"&gt;new &lt;/span&gt;Date(today.getTime() + 365 * 24 * 60 * 60 * 1000);
            &lt;span style="color: blue;"&gt;var &lt;/span&gt;url = window.location.href.replace(/#[^#]*$/, &lt;span style="color: maroon;"&gt;''&lt;/span&gt;);
            document.cookie = &lt;span style="color: maroon;"&gt;'lcid=' &lt;/span&gt;+ value + &lt;span style="color: maroon;"&gt;';path=/;expires=' &lt;/span&gt;+ oneYear.toGMTString();
            window.location.href = url;
        }
    }

    Sys.Application.add_navigate(&lt;span style="color: blue;"&gt;function &lt;/span&gt;(sender, e) {
        &lt;span style="color: blue;"&gt;var &lt;/span&gt;state = e.get_state();

        &lt;span style="color: darkgreen;"&gt;// Валидируем значения, т.к. они получены из Query String и могут быть потенциально небезопасны
        &lt;/span&gt;&lt;span style="color: blue;"&gt;var &lt;/span&gt;view = parseInt(state.view);
        &lt;span style="color: blue;"&gt;var &lt;/span&gt;filter = parseInt(state.filter);
        &lt;span style="color: blue;"&gt;var &lt;/span&gt;prefs = parseInt(state.prefs);

        &lt;span style="color: blue;"&gt;if &lt;/span&gt;(isNaN(view) || isNaN(filter) || isNaN(prefs))
            &lt;span style="color: blue;"&gt;return&lt;/span&gt;;

        DW.TasksDashboard.ViewManager.RestorePreviouslySavedView(state);
    });

    &lt;span style="color: blue;"&gt;function &lt;/span&gt;onDataLoaded() {
        Sys.Application.addHistoryPoint({
            view: DW.TasksDashboard.ViewManager.get_CurrentViewFlags(),
            filter: DW.TasksDashboard.ViewManager.get_CurrentFilterFlags(),
            prefs: DW.TasksDashboard.ViewManager.get_CurrentAdditionalFlags()
        });
    }

}

DW.TasksDashboard.UniqueURLs = &lt;span style="color: blue;"&gt;new &lt;/span&gt;DW.TasksDashboard._UniqueURLs();
_spBodyOnLoadFunctionNames.push(&lt;span style="color: maroon;"&gt;"DW.TasksDashboard.UniqueURLs.FixOnFlyLocalization"&lt;/span&gt;);

&lt;span style="font-family: &amp;quot;Arial&amp;quot;;"&gt;Он зависит от некоторых других классов моего проекта, но я надеюсь, он очень хорошо демонстрирует концепцию паттерна UniqueURLs, и заодно, этот пример должен вам помочь правильно изолировать логику UniqueURLs от всего остального решения. Мне кажется, здесь эта логика изолирована очень удачно.&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;span style="font-family: &amp;quot;Arial&amp;quot;;"&gt;В итоге, адресная строка моего дашбоарда выглядит примерно так:&lt;/span&gt;&lt;/pre&gt;
&lt;span style="font-family: &amp;quot;Arial&amp;quot;;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;pre class="code"&gt;&lt;a href="http://lh3.ggpht.com/-HMLwVh6M3kI/T8O1f1D4F2I/AAAAAAAABXs/DSAiVF5ZTho/s1600-h/image%25255B17%25255D.png"&gt;&lt;img alt="image" border="0" height="231" src="http://lh6.ggpht.com/-zUOI0Ua9q34/T8O1gzM7EvI/AAAAAAAABX0/s2qM_dJe1Nw/image_thumb%25255B11%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="836" /&gt;&lt;/a&gt;&lt;/pre&gt;
&lt;br /&gt;
, т.е. параметры в строке состояния полностью соответствуют положению переключателей в трех разных группах на контекстной ленте (Views, Filters и Preferences). И если мы начинаем переключать кнопки на ленте, эти переключения тут же отражаются в адресной строке.&lt;br /&gt;
&lt;br /&gt;
Мне кажется, это очень классно и очень удобно. Решается как минимум одна бизнес-задача: например, если клиент вдруг захочет, чтобы для всех пользователей дашбоард открывался по умолчанию на фильтре “Задачи, назначенные на меня моим руководителем”, или на какой-то другой особой комбинации настроек/фильтров/представлений, то он сможет просто отредактировать ссылку в главном меню – и вуаля, проблема решена.&lt;br /&gt;
&lt;br /&gt;
Подводя итог: очень рекомендую обратить внимание на Ajax-паттерны и использовать их, если они подходят вашему решению – часто эти паттерны требуют совершенно пустяковых затрат в реализации, но зато могут значительно повысить удобство ваших интерфейсов, особенно если вы реализуете не один, а хотя бы 2-3 паттерна. Список Ajax-паттернов можно найти на сайте &lt;a href="http://ajaxpatterns.org/"&gt;AjaxPatterns.org&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-1082574766710315712?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/_6VubIYZpW4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/1082574766710315712/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/uniqueurls-sharepoint.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1082574766710315712?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1082574766710315712?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/_6VubIYZpW4/uniqueurls-sharepoint.html" title="Реализация паттерна UniqueURLs в SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-NJz5SanQzKg/T8OnmBWetOI/AAAAAAAABXg/KwGYBWb1vXI/s72-c/image_thumb%25255B8%25255D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/uniqueurls-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYCQHY5eCp7ImA9WhVbE08.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-5581316715202833055</id><published>2012-05-29T09:20:00.000+04:00</published><updated>2012-05-30T00:26:01.820+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-30T00:26:01.820+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>PowerShell-скрипт для генерации задач</title><content type="html">В посте &lt;a href="http://omlin.blogspot.com/2012/02/sharepoint.html"&gt;Генерация большого числа записей в список SharePoint&lt;/a&gt; я описывал, как можно легко сгенерировать много записей и вставить их в произвольный список. Однако, всегда хочется иметь в качестве тестовых более-менее реалистичные данные, разнообразные и полные. В этом посте я хочу привести скрипт для генерации записей для стандартного списка задач.&lt;br /&gt;
На основе этого скрипта, я верю, что вам удастся сформировать решения для генерации более реалистичных данных для ваших тестов.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;Для каждого из типов полей я написал собственную маленькую функцию для генерации значений этого поля.&lt;br /&gt;
Например, вот эта функция:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: purple;"&gt;$random &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: cadetblue;"&gt;New-Object &lt;/span&gt;&lt;span style="color: maroon;"&gt;System.Random&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomDay&lt;/span&gt;&lt;span style="color: black;"&gt;()
{
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$start &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: cadetblue;"&gt;New-Object &lt;/span&gt;&lt;span style="color: maroon;"&gt;System.DateTime&lt;/span&gt;&lt;span style="color: black;"&gt;(1995, 1, 1);

    &lt;/span&gt;&lt;span style="color: purple;"&gt;$range &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: black;"&gt;([&lt;/span&gt;&lt;span style="color: teal;"&gt;System.TimeSpan&lt;/span&gt;&lt;span style="color: black;"&gt;]([&lt;/span&gt;&lt;span style="color: teal;"&gt;System.DateTime&lt;/span&gt;&lt;span style="color: black;"&gt;]::&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Today &lt;/span&gt;&lt;span style="color: red;"&gt;- &lt;/span&gt;&lt;span style="color: purple;"&gt;$start&lt;/span&gt;&lt;span style="color: black;"&gt;)).Days;           
    &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.DateTime&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$start&lt;/span&gt;&lt;span style="color: black;"&gt;.AddDays(&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(&lt;/span&gt;&lt;span style="color: purple;"&gt;$range&lt;/span&gt;&lt;span style="color: black;"&gt;));
}&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
, вернет случайную дату. Полученные с её помощью значения можно использовать для заполнения колонок “Start Date” и “Due Date”.&lt;br /&gt;
&lt;br /&gt;
Функции по генерации приоритета, статуса и прогресса задачи также довольно простые:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomPriority&lt;/span&gt;&lt;span style="color: black;"&gt;()
{
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$priorities &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"(1) High"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"(2) Normal"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"(2) Normal"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"(2) Normal"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"(3) Low"
    &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$priorities&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(0,5)]
}
&lt;/span&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomStatus&lt;/span&gt;&lt;span style="color: black;"&gt;()
{
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$status &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Completed"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Deferred"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"In Progress"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Not Started"
    &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$status&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(0,4)]
}
&lt;/span&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomProgress&lt;/span&gt;&lt;span style="color: black;"&gt;()
{
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$r &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(0,20) &lt;/span&gt;&lt;span style="color: red;"&gt;* &lt;/span&gt;&lt;span style="color: black;"&gt;5);
    &lt;/span&gt;&lt;span style="color: blue;"&gt;if &lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$r &lt;/span&gt;&lt;span style="color: red;"&gt;-lt &lt;/span&gt;&lt;span style="color: black;"&gt;10)
    {
       &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: maroon;"&gt;"0.0" &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: purple;"&gt;$r
    &lt;/span&gt;&lt;span style="color: black;"&gt;}
    &lt;/span&gt;&lt;span style="color: blue;"&gt;else
    &lt;/span&gt;&lt;span style="color: black;"&gt;{
       &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: maroon;"&gt;"0." &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: purple;"&gt;$r
    &lt;/span&gt;&lt;span style="color: black;"&gt;}
}&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
Более интересна функция по генерации заголовка задачи. Она определяет список действий и список контрагентов (названия контрагентов взяты из базы NorthWind), берет по одному значению из каждого списка, и склеивает их в единую строку. Вот так:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomTitle&lt;/span&gt;&lt;span style="color: black;"&gt;()
{
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$agents &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Alfreds Futterkiste"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Ana Trujillo Emparedados y helados"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Antonio Moreno Taqueria"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Around the Horn"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Berglunds snabbkop"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Blauer See Delikatessen"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Blondesddsl pere et fils"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Bolido Comidas preparadas"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Bon app"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Bottom-Dollar Markets"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"B's Beverages"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Cactus Comidas para llevar"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Centro comercial Moctezuma"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Chop-suey Chinese"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Comercio Mineiro"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Consolidated Holdings"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Drachenblut Delikatessen"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Du monde entier"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Eastern Connection"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Ernst Handel"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Familia Arquibaldo"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"FISSA Fabrica Inter. Salchichas S.A."&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Folies gourmandes"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Folk och fa HB"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Frankenversand"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"France restauration"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Franchi S.p.A."&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Furia Bacalhau e Frutos do Mar"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Galeria del gastronomo"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Godos Cocina Tipica"&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Gourmet Lanchonetes"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Great Lakes Food Market"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Hanari Carnes"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GROSELLA-Restaurante"&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"HILARION-Abastos"
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$actions &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Arrange a meeting with "&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Demonstrate the product to "&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Call "&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Meet "&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Discuss possibilities with "&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Sign contract with "&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Implement request from "&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Prepare materials for "&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Prepare documents for "&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Accord document with "&lt;/span&gt;&lt;span style="color: black;"&gt;,
        &lt;/span&gt;&lt;span style="color: maroon;"&gt;"Prepare advertisement for "
    &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$actions&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(0,12)] &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: purple;"&gt;$agents&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: purple;"&gt;$random&lt;/span&gt;&lt;span style="color: black;"&gt;.Next(0,35)]
}&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
Наконец, нужно определить функцию, которая генерит XML для массового добавления записей через &lt;i&gt;ProcessBatchData&lt;/i&gt;:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;function &lt;/span&gt;&lt;span style="color: navy;"&gt;Generate50Tasks&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$listID&lt;/span&gt;&lt;span style="color: black;"&gt;)
{
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;Method ID=""{0}""&amp;gt;&amp;lt;SetList&amp;gt;" &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: purple;"&gt;$listID &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;/SetList&amp;gt;`n"&lt;/span&gt;&lt;span style="color: black;"&gt;;
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""Cmd""&amp;gt;Save&amp;lt;/SetVar&amp;gt;`n&amp;lt;SetVar Name=""ID""&amp;gt;New&amp;lt;/SetVar&amp;gt;`n"&lt;/span&gt;&lt;span style="color: black;"&gt;;
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#Title""&amp;gt;{1}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#StartDate""&amp;gt;{2}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#DueDate""&amp;gt;{3}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#Priority""&amp;gt;{4}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#Status""&amp;gt;{5}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;SetVar Name=""urn:schemas-microsoft-com:office:office#PercentComplete""&amp;gt;{6}&amp;lt;/SetVar&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$method &lt;/span&gt;&lt;span style="color: red;"&gt;+= &lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;/Method&amp;gt;`n"
  &lt;/span&gt;&lt;span style="color: purple;"&gt;$methods &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: maroon;"&gt;""
  &lt;/span&gt;&lt;span style="color: blue;"&gt;for&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$i &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: black;"&gt;1;&lt;/span&gt;&lt;span style="color: purple;"&gt;$i &lt;/span&gt;&lt;span style="color: red;"&gt;-le &lt;/span&gt;&lt;span style="color: black;"&gt;50; &lt;/span&gt;&lt;span style="color: purple;"&gt;$i&lt;/span&gt;&lt;span style="color: black;"&gt;++)
  {
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$title &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomTitle
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$startDate &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomDay
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$dueDate &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomDay
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$priority &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomPriority
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$status &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomStatus
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$percentComplete &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;RandomProgress
    &lt;/span&gt;&lt;span style="color: purple;"&gt;$methods &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: purple;"&gt;$methods &lt;/span&gt;&lt;span style="color: red;"&gt;+ &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]::&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Format&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$method&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$i&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$title&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$startDate&lt;/span&gt;&lt;span style="color: black;"&gt;.ToString(&lt;/span&gt;&lt;span style="color: maroon;"&gt;"s"&lt;/span&gt;&lt;span style="color: black;"&gt;), &lt;/span&gt;&lt;span style="color: purple;"&gt;$dueDate&lt;/span&gt;&lt;span style="color: black;"&gt;.ToString(&lt;/span&gt;&lt;span style="color: maroon;"&gt;"s"&lt;/span&gt;&lt;span style="color: black;"&gt;), &lt;/span&gt;&lt;span style="color: purple;"&gt;$priority&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$status&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$percentComplete&lt;/span&gt;&lt;span style="color: black;"&gt;.ToString().Replace(&lt;/span&gt;&lt;span style="color: maroon;"&gt;","&lt;/span&gt;&lt;span style="color: black;"&gt;,&lt;/span&gt;&lt;span style="color: maroon;"&gt;"."&lt;/span&gt;&lt;span style="color: black;"&gt;))
  }
  &lt;/span&gt;&lt;span style="color: blue;"&gt;return &lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: teal;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;]::&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Format&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: maroon;"&gt;"&amp;lt;?xml version=""1.0"" encoding=""UTF-8""?&amp;gt;&amp;lt;ows:Batch OnError=""Return""&amp;gt;{0}&amp;lt;/ows:Batch&amp;gt;"&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: purple;"&gt;$methods&lt;/span&gt;&lt;span style="color: black;"&gt;);
}&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
Генерация 50 записей обеспечивает относительную уникальность заголовков. Конечно, можно генерировать и по 150 записей, и нагенерить несколько тысяч задач, – но это требуется не так часто.&lt;br /&gt;
&lt;br /&gt;
Давайте, наконец, сгенерируем записи:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: purple;"&gt;$web &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: black;"&gt;Get-SPWeb http://localhost&lt;/span&gt;
&lt;span style="color: purple;"&gt;$list &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: purple;"&gt;$web&lt;/span&gt;&lt;span style="color: black;"&gt;.Lists[&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Tasks"&lt;/span&gt;&lt;span style="color: black;"&gt;]
&lt;/span&gt;&lt;span style="color: purple;"&gt;$xml &lt;/span&gt;&lt;span style="color: red;"&gt;= &lt;/span&gt;&lt;span style="color: navy;"&gt;Generate50Tasks &lt;/span&gt;&lt;span style="color: purple;"&gt;$list&lt;/span&gt;&lt;span style="color: black;"&gt;.ID&lt;/span&gt;
&lt;span style="color: purple;"&gt;$web&lt;/span&gt;&lt;span style="color: black;"&gt;.ProcessBatchData(&lt;/span&gt;&lt;span style="color: purple;"&gt;$xml&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
Здесь исправьте хост/порт и заголовок списка на тот, который соответствует вашему порталу.&lt;br /&gt;
&lt;br /&gt;
Также, вы можете &lt;a href="https://sites.google.com/site/omlinfiles/generateTasks.ps1?attredirects=0&amp;amp;d=1"&gt;скачать скрипт в виде файла&lt;/a&gt;. Если у вас русский портал, у меня есть и &lt;a href="https://sites.google.com/site/omlinfiles/generateTasksRu.ps1?attredirects=0&amp;amp;d=1"&gt;русская версия скрипта&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
После генерации, получите примерно такую картинку:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh3.ggpht.com/-0CHVfoeLTts/T8KbUtpmCzI/AAAAAAAABWQ/turOa0pVy2I/s1600-h/image%25255B4%25255D.png"&gt;&lt;img alt="image" border="0" height="328" src="http://lh4.ggpht.com/-QjFSLWU8l0c/T8KbVVuULjI/AAAAAAAABWY/bU76N8dypP0/image_thumb%25255B2%25255D.png?imgmax=800" style="background-image: none; border: 0px none currentcolor; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="759" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Если использовать русский скрипт, картинка будет немного другой:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-gjjKhyY90U0/T8NIN-04kSI/AAAAAAAABWs/qC6pOCFzUc4/s1600/generatedTasksRu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="330" src="http://4.bp.blogspot.com/-gjjKhyY90U0/T8NIN-04kSI/AAAAAAAABWs/qC6pOCFzUc4/s1600/generatedTasksRu.png" width="759" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-5581316715202833055?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/slbJFypszJM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/5581316715202833055/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/powershell.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5581316715202833055?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5581316715202833055?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/slbJFypszJM/powershell.html" title="PowerShell-скрипт для генерации задач" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-QjFSLWU8l0c/T8KbVVuULjI/AAAAAAAABWY/bU76N8dypP0/s72-c/image_thumb%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/powershell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYEQX0zfip7ImA9WhVbEUU.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-6042772904810433812</id><published>2012-05-28T09:15:00.000+04:00</published><updated>2012-05-28T09:15:00.386+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-28T09:15:00.386+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="WSS3" /><category scheme="http://www.blogger.com/atom/ns#" term="MOSS2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Русскоязычные SharePoint-блоггеры</title><content type="html">&lt;p&gt;К сожалению, людей, &lt;strong&gt;хорошо&lt;/strong&gt; пишущих про SharePoint на русском языке — единицы. Под «хорошо» я имею в виду уникальный, интересный контент, грамотно оформленный и представляющий практическую ценность. Впрочем, несколько человек всё-таки есть, и сегодня мне хочется о них рассказать и обратить на них внимание общественности, потому что, к сожалению, нередко эти блоги далеко не настолько популярны, насколько они этого заслуживают (возможно, причина в том, что многие SharePoint-разработчики свои запросы в гугле набирают исключительно по-английски?...).&lt;/p&gt; &lt;p&gt;Итак, поехали...&lt;/p&gt; &lt;a name='more'&gt;&lt;/a&gt; &lt;h2&gt;Стас Выщепан&lt;/h2&gt; &lt;p&gt;Стас — наверное один из самых знающих людей по SharePoint, причем не только среди русскоязычных экспертов. В 2011м году он был совершенно заслуженно награжден статусом SharePoint MVP, также он имеет статус MCT (Microsoft Certified Trainer) и большой опыт работы в роли тренера. Он знает намного больше меня во многих областях, и проповедует несколько очень интересных техник разработки под SharePoint. С ним всегда очень интересно общаться, его доклады — интересно слушать, и также он пишет очень подробные и понятные статьи.&lt;/p&gt; &lt;p&gt;Самое интересное, что у него есть статьи по вроде бы простым темам, которые написаны вглубь, рассказывают о множестве нюансов и о таких тонкостях, которые не знают даже люди, работающие с SharePoint не один год. По сути дела, это бесценные материалы, которые могут сэкономить не просто часы, но дни и даже недели борьбы с «особенностями» SharePoint, скажем так.&lt;/p&gt; &lt;p&gt;Особенно я хочу отметить две серии статей из блога Стаса, про простое в глубину:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;a href="http://gandjustas.blogspot.com/2011/05/blog-post.html"&gt;Про Event Receiver’ы&lt;/a&gt; (есть и &lt;a href="http://gandjustas.blogspot.com/2011/06/2.html"&gt;вторая часть&lt;/a&gt;)&lt;/li&gt; &lt;li&gt;&lt;a href="http://gandjustas.blogspot.com/2011/10/blog-post.html"&gt;Про Timer Job’ы&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;У него в блоге, конечно же, есть и множество других крайне полезных статей, и если вы еще не подписаны на него или не читали — давно пора исправить это недоразумение! :)&lt;/p&gt; &lt;h2&gt;Игорь Акимов&lt;/h2&gt; &lt;p&gt;Я не знаю Игоря лично, но меня зацепили несколько постов из его блога, которые я случайно недавно прочитал. Если он будет продолжать в таком духе, я уверен, что его блог вполне может превратиться для многих людей в первоклассный источник уникальных знаний по SharePoint.&lt;/p&gt; &lt;p&gt;Например, &lt;a href="http://www.aviw.net/2012/05/spchangequery.html"&gt;один из последних его постов&lt;/a&gt; рассказывает о малоизвестном и, как водится, недокументированном ActiveX-контроле, который в SharePoint используется для массовой загрузки файлов на сервер.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.aviw.net/2012/05/blog-post.html"&gt;Другой пост&lt;/a&gt; Игоря повествует о том, что оказывается страницы веб-частей можно развертывать с помощью метода ProcessBatchData. К слову, этот метод вообще очень интересный, и помимо развертывания веб-частей и наиболее известных операций по массовому добавлению/изменению элементов списка умеет еще много чего (о чем почти никто не знает). В блоге у Stefan Stanev (англоязычном) можно найти &lt;a href="http://stefan-stanev-sharepoint-blog.blogspot.com/search?q=ProcessBatchData"&gt;несколько других вкусностей о ProcessBatchData&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;Виталий Жуков&lt;/h2&gt; &lt;p&gt;Виталий Жуков впервые привлек мое внимание серией статей по обзору DeskWork :), в создании которого я принимаю участие в течение последних более чем 2х лет работы в Softline. И лишь позже я обнаружил, что у него в блоге много и других интересных постов, и посты эти появляются просто-таки стремительно :)&lt;/p&gt; &lt;p&gt;Прежде всего, хочется сказать, что Виталий — один из на самом деле немногих людей, кто всерьез работает с Linq-To-SharePoint. В его блоге вы найдете целую &lt;a href="http://blog.vitalyzhukov.ru/ru/tag/Linq-To-SharePoint.aspx"&gt;серию статей про Linq-To-SharePoint&lt;/a&gt;, про особенности работы с ним, его возможности и т.д.&lt;/p&gt; &lt;p&gt;У Виталия есть и другие статьи. Например, меня очень заинтересовала &lt;a href="http://blog.vitalyzhukov.ru/ru/missing-ListTitleViewSelectorMenu.aspx"&gt;статья про ListTitleViewSelectorMenu&lt;/a&gt;. Проблема очень распространенная: если на страницу представления списка подложить веб-часть фильтрации, то из заголовка страницы тут же исчезает меню выбора текущего представления. К сожалению, в статье мало подробностей и нет исходного кода, но суть решения понятна, и в некоторых случаях, мне кажется, такое решение вполне имеет право на жизнь.&lt;/p&gt; &lt;p&gt;Другая понравившаяся статья — про то, &lt;a href="http://blog.vitalyzhukov.ru/ru/disabled-users-and-people-picker.aspx"&gt;как запретить выбирать отключенных в AD пользователей в PeoplePicker&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;Alejo El Norte&lt;/h2&gt; &lt;p&gt;&lt;a href="http://sharegpoint.blogspot.com/"&gt;Блог Alejo El Norte&lt;/a&gt; был создан совсем недавно, но уже сейчас даже опытные SharePoint-эксперты могут с удивлением обнаружить там некоторые очень полезные штуковины, о которых они не знали :) На текущий момент, наиболее интересными для меня постами являются посты про Download.aspx, CopyUtil.aspx, и клиентскую функцию GoToPage. Ни одной из этих фишек я на момент прочтения не знал. Если так будет продолжаться и дальше, у этого блога — большое будущее :)&lt;/p&gt; &lt;h2&gt;Другие блоги&lt;/h2&gt; &lt;p&gt;Хочется также упомянуть блоги Антона Вишнякова и Игоря Афанасова. Эти блоги на текущий момент не очень активны, но в любом случае, авторы успели написать немало интересных постов, которые стоит почитать.&lt;/p&gt; &lt;p&gt;У Игоря Афанасова — немало &lt;a href="http://rusharepoint2010.blogspot.com/search/label/заметки%20о%20книгах"&gt;заметок о книгах по SharePoint&lt;/a&gt;. Также мне очень понравилась последняя заметка из его блога: &lt;a href="http://rusharepoint2010.blogspot.com/2012/03/sharepoint.html"&gt;Полезные протоколы SharePoint&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Антон Вишняков много писал &lt;a href="http://avishnyakov.wordpress.com/tag/infopath-2010/"&gt;про InfoPath&lt;/a&gt;. Также, в его блоге можно найти несколько забавных ошибок в SharePoint, и несколько очень правильных «no code» решений.&lt;/p&gt; &lt;h2&gt;Заключение&lt;/h2&gt; &lt;p&gt;Русскоязычных блогов по SharePoint немного, высококлассных — и вовсе единицы. Но всё же, они есть. И нельзя об этом забывать, потому что нередко в русскоязычных блогах можно найти даже то, что больше нигде, и ни на каком другом языке, найти не получится.&lt;/p&gt; &lt;p&gt;Если вы знаете другие хорошие блоги по SharePoint, с хорошими и уникальными статьями, пожалуйста, напишите в комментариях! Просьба также указать статьи, которые вам понравились в этих блогах.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-6042772904810433812?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/3-ArdC0aArM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/6042772904810433812/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/sharepoint.html#comment-form" title="Комментарии: 12" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6042772904810433812?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6042772904810433812?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/3-ArdC0aArM/sharepoint.html" title="Русскоязычные SharePoint-блоггеры" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><thr:total>12</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMESXg6eCp7ImA9WhVbEUw.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-5208649318902942396</id><published>2012-05-27T15:11:00.001+04:00</published><updated>2012-05-27T15:16:48.610+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-27T15:16:48.610+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="кодогенерация" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><title>Генерация JS из C# с помощью T4</title><content type="html">В Ajax-приложениях данные передаются между клиентской и серверной стороной. Естественно, что структуру этих данных необходимо знать и на клиенте, и на сервере. Обычно это означает ведение одних и тех же классов, интерфейсов и перечислений и в виде JS-файлов, и в виде C#-файлов. Это лишняя работа, неудобно и вообще опасно.&lt;br /&gt;
&lt;br /&gt;
В одном месте поменял, в другом забыл – получил баг. У меня был такой опыт: изменил перечисление на сервере, на клиенте забыл. В итоге логика работы кнопок &lt;i&gt;иногда&lt;/i&gt; стала подглючивать, только при определенной комбинации фильтров и т.д. Ошибку обнаружили тестировщики,&amp;nbsp; через пару дней проверок, к тому времени я конечно уже давно забыл, что я менял перечисление и зачем я это делал. В итоге, чтобы локализовать ошибку, мне пришлось потратить больше часа времени...&lt;br /&gt;
&lt;br /&gt;
Чтобы избавиться от такого рода ошибок и от лишней работы, я использую T4-преобразования, и генерирую JS-файлы на основе C#. В этой статье я расскажу, как такие преобразования устроены и работают. В конце статьи выложен код итогового T4-преобразования, которое можно скачать и использовать в ваших собственных проектах без изменений. Итак, поехали!&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;



Code Model&lt;/h2&gt;
Code Model – это функциональность, предоставляемая Visual Studio, позволяющая просматривать (и даже изменять) описания классов, методов, свойств и полей во всем вашем проекте. Похоже на Reflection, но намного удобнее. Подробнее о Code Model можно &lt;a href="http://msdn.microsoft.com/en-us/library/ms228763.aspx"&gt;прочитать на MSDN&lt;/a&gt;.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Замечание&lt;/i&gt;&lt;/b&gt;: Code Model работает только в среде Visual Studio, поэтому использующие этот функционал T4-преобразования нельзя запускать за пределами VS, например в &lt;a href="http://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%BF%D1%80%D0%B5%D1%80%D1%8B%D0%B2%D0%BD%D0%B0%D1%8F_%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F"&gt;Continious Integration&lt;/a&gt;-билдах.&lt;br /&gt;
&lt;br /&gt;
Code Model позволяет перебирать все элементы кода, и у каждого из этих элементов есть коллекция Children, которую тоже можно перебрать, и т.д.&lt;br /&gt;
Простейший пример использования Code Model выглядит примерно так:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span style="color: blue;"&gt;foreach &lt;/span&gt;(EnvDTE.CodeElement element &lt;span style="color: blue;"&gt;in &lt;/span&gt;projectItem.FileCodeModel.CodeElements)
{
    &lt;span style="color: blue;"&gt;if &lt;/span&gt;(element.Kind == EnvDTE.vsCMElement.vsCMElementNamespace)
    {
        &lt;span style="color: blue;"&gt;foreach &lt;/span&gt;(EnvDTE.CodeElement innerElement &lt;span style="color: blue;"&gt;in &lt;/span&gt;element.Children)
        {
            &lt;span style="color: blue;"&gt;switch &lt;/span&gt;(innerElement.Kind)
            {
                &lt;span style="color: blue;"&gt;case &lt;/span&gt;EnvDTE.vsCMElement.vsCMElementClass:
                    Debug.WriteLine(&lt;span style="color: #a31515;"&gt;"Class: " &lt;/span&gt;+ innerElement.Name);
                    &lt;span style="color: blue;"&gt;break&lt;/span&gt;;
                &lt;span style="color: blue;"&gt;case &lt;/span&gt;EnvDTE.vsCMElement.vsCMElementEnum:
                    Debug.WriteLine(&lt;span style="color: #a31515;"&gt;"Enum: " &lt;/span&gt;+ innerElement.Name);
                    &lt;span style="color: blue;"&gt;break&lt;/span&gt;;
                &lt;span style="color: blue;"&gt;case &lt;/span&gt;EnvDTE.vsCMElement.vsCMElementInterface:
                    Debug.WriteLine(&lt;span style="color: #a31515;"&gt;"Interface: " &lt;/span&gt;+ innerElement.Name);
                    &lt;span style="color: blue;"&gt;break&lt;/span&gt;;
            }
        }
    }
}&lt;/pre&gt;
&lt;br /&gt;
Соответственно, если взглянуть дальше вглубь классов/перечислений/интерфейсов, сгенерировать их описания для JavaScript довольно легко.&lt;br /&gt;
&lt;br /&gt;
Кстати, очень хороший пример с генерацией SQL-таблиц на основе C#-перечислений с использованием T4 и Code Model &lt;a href="http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/"&gt;можно найти у Олега Сыча&lt;/a&gt;. У Олега в блоге вообще очень много про T4, рекомендую почитать.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;



ООП и ASP.Net Ajax&lt;/h2&gt;
Для реализации ООП в JavaScript я использую в своих проектах библиотеку ASP.Net Ajax. К слову, эта библиотека (версии 3.5) уже присутствует в составе SharePoint, так что SharePoint-разработчикам ничего дополнительно подключать не потребуется.&lt;br /&gt;
&lt;br /&gt;
Как известно, JavaScript не является объектно-ориентированным языком, поэтому ООП-объекты JavaScript выглядят порой довольно неказисто. Например, чтобы объявить перечисление в ASP.Net Ajax, при этом используя inline-документацию, нужно написать довольно много кода. Реальный пример из рабочего проекта:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;DW.TasksDashboard.DashboardFilter = &lt;span style="color: blue;"&gt;function&lt;/span&gt;() {
    &lt;span style="color: darkgreen;"&gt;/// &amp;lt;summary&amp;gt;Предустановленные фильтры для Центра задач&amp;lt;/summary&amp;gt;
    /// &amp;lt;field name='AllTasks' type='Number' integer='true' static='true'&amp;gt;Все задачи (без фильтрации)&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='TasksAssignedToMe' type='Number' integer='true' static='true'&amp;gt;Задачи, назначенные на текущего пользователя&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='TasksCreatedByMe' type='Number' integer='true' static='true'&amp;gt;Задачи, созданные текущим пользователем&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='ManagerTasks' type='Number' integer='true' static='true'&amp;gt;Задачи, созданные руководителем текущего пользователя и назначенные на текущего пользователя&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='DepartmentTasks' type='Number' integer='true' static='true'&amp;gt;Задачи, назначенные на членов отдела текущего пользователя (включая его самого)&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='DeputyTasks' type='Number' integer='true' static='true'&amp;gt;Задачи, назначенные на пользователей, которых замещает текущий пользователь&amp;lt;/field&amp;gt;
    /// &amp;lt;field name='SecretaryTasks' type='Number' integer='true' static='true'&amp;gt;Задачи, назначенные на пользователей, для которых текущий пользователь - секретарь&amp;lt;/field&amp;gt;&lt;/span&gt;}

DW.TasksDashboard.DashboardFilter.prototype = {
    AllTasks: 1,
    TasksAssignedToMe: 2,
    TasksCreatedByMe: 3,
    ManagerTasks: 4,
    DepartmentTasks: 5,
    DeputyTasks: 6,
    SecretaryTasks: 7
}
DW.TasksDashboard.DashboardFilter.registerEnum(&lt;span style="color: maroon;"&gt;'DW.TasksDashboard.DashboardFilter'&lt;/span&gt;);&lt;/pre&gt;
&lt;br /&gt;
Как описывать другие ООП-объекты с помощью ASP.Net Ajax (классы, интерфейсы, события и т.д.), вы можете найти в документации по этой библиотеке, например в статье &lt;a href="http://www.asp.net/AJAX/Documentation/Live/tutorials/EnhancingJavaScriptTutorial.aspx"&gt;Extending JavaScript with ASP.NET AJAX&lt;/a&gt;. Имея это знание, написать итоговый код несложно. Взамен, вы можете использовать &lt;a href="https://sites.google.com/site/omlinfiles/Shared.tt?attredirects=0&amp;amp;d=1"&gt;t4-файл, который написал я&lt;/a&gt;. Просто добавьте его в проект, и измените пути к файлам, которые необходимо обрабатывать.&lt;br /&gt;
&lt;h2&gt;



Заключение&lt;/h2&gt;
Принцип DRY (Do not repeat yourself) – это один из основополагающих принципов в программировании. Его соблюдение дает множество преимуществ. И даже если без повторения одного и того же кода не обойтись, как это имеет место быть в случае Ajax-приложений с общей моделью данных, T4-шаблоны могут помочь в этой ситуации, и сгенерировать нужный код автоматически.&lt;br /&gt;
&lt;br /&gt;
К слову, генерация JS-кода на основе C# также является паттерном, одним из т.н. Ajax-паттернов, т.е. специально заточенных под Ajax-приложения. Этот паттерн называется &lt;a href="http://ajaxpatterns.org/Server-Side_Code_Generation"&gt;Server-Side Code Generation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Другим способом генерации JS на основе C#, более общим, является использование &lt;a href="http://projects.nikhilk.net/ScriptSharp"&gt;Script#&lt;/a&gt; – этот проект позволяет компилировать С#-код в JavaScript, и активно используется даже во внутренней разработке в компании Microsoft. В частности, судя по всему, &lt;a href="http://weblogs.asp.net/soever/archive/2009/10/20/sharepoint-2010-client-side-javascript-object-model-library-written-in-script.aspx"&gt;SharePoint Client Object Model тоже написан на Script#&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-5208649318902942396?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/OH5bksYJUEU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/5208649318902942396/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/js-c-t4.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5208649318902942396?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5208649318902942396?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/OH5bksYJUEU/js-c-t4.html" title="Генерация JS из C# с помощью T4" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/js-c-t4.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYARHc9fip7ImA9WhVbEUg.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-4103623393988332569</id><published>2012-05-25T21:11:00.001+04:00</published><updated>2012-05-28T00:55:45.966+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-28T00:55:45.966+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="кодогенерация" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajax" /><title>Разработка больших JavaScript-решений: 1 файл = 1 класс</title><content type="html">В наши дни JavaScript-кода писать приходится все больше и больше. Единственный способ справляться с большим количеством кода – это разбивать его, структурировать, дробить на небольшие и понятные кусочки. Я лично в этом отношении использую два простых правила:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;1 класс = 1 файл  &lt;/li&gt;
&lt;li&gt;В 1 файле – не более 300 строк&lt;/li&gt;
&lt;/ol&gt;
Эти правила отлично работают и для серверного кода, и для клиентского. Но если серверный код автоматически, средствами Visual Studio, компилируется в единственный dll-файл, то JavaScript приходится склеивать в один кусок “вручную”.&lt;br /&gt;
&lt;br /&gt;
В этом посте я хочу рассказать, как это можно сделать.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
А сделать это можно разными способами... Например, &lt;a href="http://msdn.microsoft.com/en-us/library/cc488552.aspx"&gt;это можно сделать с помощью свойства CompositeScript объекта ScriptManager&lt;/a&gt;. Но &lt;a href="http://www.wictorwilen.se/Post/Understanding-the-SharePoint-2010-Sandbox-limitations.aspx"&gt;ScriptManager частично не работает в SharePoint Sandbox&lt;/a&gt;, и к тому же этот вариант не позволяет произвести минификацию итогового JavaScript.&lt;br /&gt;
&lt;br /&gt;
Поэтому я использую для склейки примитивное T4-преобразование. Например, давайте предположим, что в корневой папке проекта у вас лежат файлы Script1.js и Script2.js:&lt;br /&gt;
&lt;a href="http://lh5.ggpht.com/-kRX4VFkb-x4/T7-9M1nKtzI/AAAAAAAABVc/UXZWy2b0KQM/s1600-h/image%25255B7%25255D.png"&gt;&lt;img alt="image" border="0" height="209" src="http://lh5.ggpht.com/-I_cooTBdXjs/T7-9N78-CzI/AAAAAAAABVg/YeOzk-Wr4Bw/image_thumb%25255B3%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /&gt;&lt;/a&gt;&lt;br /&gt;
Чтобы их склеить, T4-шаблон будет следующим:&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&amp;lt;#@ template debug=&lt;span class="str"&gt;"false"&lt;/span&gt; hostspecific=&lt;span class="str"&gt;"true"&lt;/span&gt; language=&lt;span class="str"&gt;"C#"&lt;/span&gt; #&amp;gt;
&amp;lt;#@ output extension=&lt;span class="str"&gt;".js"&lt;/span&gt; #&amp;gt;
&amp;lt;#@ Import Namespace=&lt;span class="str"&gt;"System.IO"&lt;/span&gt; #&amp;gt;

Type.registerNamespace(&lt;span class="str"&gt;"MyCompany.MyNamespace"&lt;/span&gt;);

&amp;lt;#= GetFileContents(&lt;span class="str"&gt;@"Script1.js"&lt;/span&gt;) #&amp;gt;
&amp;lt;#= GetFileContents(&lt;span class="str"&gt;@"Script2.js"&lt;/span&gt;) #&amp;gt;

&amp;lt;#+

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFileContents(&lt;span class="kwrd"&gt;string&lt;/span&gt; filename)
    {
        var path = Path.GetDirectoryName(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Host.TemplateFile);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; File.ReadAllText(Path.Combine(path, filename));
    }

#&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
Этот код нужно добавить в файл типа “Text Template”:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh6.ggpht.com/-Ia8ZD1BHM1s/T7-9OjCof9I/AAAAAAAABVs/FHgHBfJD03o/s1600-h/image%25255B4%25255D.png"&gt;&lt;img alt="image" border="0" height="329" src="http://lh4.ggpht.com/-uH7HrojkGx4/T7-9ProG-XI/AAAAAAAABV0/6LRFKa1vjdM/image_thumb%25255B2%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="660" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Как только вы скопипастите код в файл и сохраните его, в подчиненном js-файле обнаружится склеенное содержимое Script1.js и Script2.js:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh5.ggpht.com/-qFPSXzD_JcI/T7-9RXvc00I/AAAAAAAABV8/rKszSKXHRFY/s1600-h/image%25255B17%25255D.png"&gt;&lt;img alt="image" border="0" height="237" src="http://lh4.ggpht.com/-SYdpL9-vTac/T7-9SexTrlI/AAAAAAAABWE/Ql9nGyEDLNU/image_thumb%25255B9%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="661" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Что ж, файлы склеили – получили “debug”-версию скрипта. Но для отгрузки на продакшн использовать такую склейку, конечно, не годится – надо бы её минифицировать. Это можно сделать очень легко с помощью утилиты Microsoft Ajax Minifier, &lt;a href="http://ajaxmin.codeplex.com/"&gt;доступной на Codeplex&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
После установки Ajax Minifier, вам потребуется прописать строку его вызова в Pre-Built Event проекта. Для нашего случая строка будет выглядеть примерно так:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-family: &amp;quot;Consolas&amp;quot;;"&gt;"C:\Program Files (x86)\Microsoft\Microsoft Ajax Minifier\AjaxMin.exe" -JS $(ProjectDir)\CompositeScript.debug.js -out $(ProjectDir)\CompositeScript.js -CLOBBER&lt;/span&gt;&lt;/blockquote&gt;
(опция -CLOBBER позволяет Minifier’у перезаписывать файлы).&lt;br /&gt;
&lt;br /&gt;
После первого билда можно включить сгенерированный файл CompositeScript.js в состав проекта.&lt;br /&gt;
&lt;br /&gt;
Таким образом, получаем две версии полного JavaScript-файла. Впоследствии обе версии можно каким-нибудь способом задеплоить в SharePoint. Контрол &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.scriptlink.aspx"&gt;ScriptLink&lt;/a&gt; автоматически будет подключать debug- или release-версию скрипта в зависимости от текущей настройки параметра debug в файле web.config.&lt;br /&gt;
&lt;br /&gt;
P.S. Также о минификации можно &lt;a href="http://www.wictorwilen.se/Post/Minifying-custom-JavaScript-files-in-SharePoint-2010.aspx"&gt;почитать у Wictor Wilen&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-4103623393988332569?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/SxqSnOXF9Wg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/4103623393988332569/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/javascript-1-1.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/4103623393988332569?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/4103623393988332569?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/SxqSnOXF9Wg/javascript-1-1.html" title="Разработка больших JavaScript-решений: 1 файл = 1 класс" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-I_cooTBdXjs/T7-9N78-CzI/AAAAAAAABVg/YeOzk-Wr4Bw/s72-c/image_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/javascript-1-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAFQX4yeCp7ImA9WhVbEUg.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-1735726176259856771</id><published>2012-05-25T15:19:00.001+04:00</published><updated>2012-05-28T00:31:50.090+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-28T00:31:50.090+04:00</app:edited><title>Впечатления от MsDevCon’12 и пара интересностей о SharePoint</title><content type="html">Вернулся с конференции MsDevCon, море впечатлений и эмоций, спешу поделиться!&lt;br /&gt;
&lt;h2&gt;


Я на конференции&lt;/h2&gt;
Напомню, я участвовал в конференции как докладчик, читал доклад “Разработка Ajax-приложений в SharePoint”. Видео докладов организаторы планируют выложить не раньше чем через неделю, так что если кто-то пропустил, придется ждать :(&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://lh5.ggpht.com/-A_EH2sUc__Q/T79rYBm1LPI/AAAAAAAABVI/Ucf7DE93gC8/s1600-h/image%25255B9%25255D.png"&gt;&lt;img alt="image" border="0" height="212" src="http://lh5.ggpht.com/-MS-6wlxTn04/T79rZPE98vI/AAAAAAAABVQ/waITpwICRC4/image_thumb%25255B5%25255D.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="427" /&gt;&lt;/a&gt;&lt;br /&gt;
В любом случае, как я и обещал на докладе, я уже опубликовал два сопутствующих поста к докладу:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2012/05/javascript-1-1.html"&gt;Как я реализовал склеивание и минификацию js-файлов&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2012/05/js-c-t4.html"&gt;Как реализовать автогенерацию JavaScript-классов модели на основе C#-классов, с помощью T4-преобразований&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;


Место проведения – "Яхонты"&lt;/h2&gt;
Качество сервиса было на самом деле просто шикарным. Организация тоже в принципе на высоте (единственный наверное недочет, это то что зона экспертов никак не была обозначена – ни на плане, ни указателями, ни вывеской). Ощущение, что съездил не просто на конференцию, но съездил отдохнуть в отпуск, и вдобавок еще и на очень классную конференцию попал :) Природа, свежий воздух, кормежка “на убой”, шикарные условия размещения. Причем, это впечатление не могла испортить даже довольно прохладная погода. И кстати, несмотря на то, что кто-то боялся комаров, комаров было на самом деле не так много, и они были не слишком навязчивыми.&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="" src="http://ms4press.ru/image.axd?picture=2012%2f5%2f1_%d0%bd%d0%be%d0%b2%d1%8b%d0%b9+%d1%80%d0%b0%d0%b7%d0%bc%d0%b5%d1%80.jpg" style="display: block; float: none; margin-left: auto; margin-right: auto;" /&gt; &lt;br /&gt;
Отдельно про официантов: официанты были просто бесподобны! :) Представьте себе гризли-подобного мужика, с руками толщиной в две обычных, и ростом под два метра. А теперь представьте его одетым в ливрею официанта :) Это было очень забавно! :)&lt;br /&gt;
&lt;h2&gt;


Хансельман&lt;/h2&gt;
Все эти условия способствовали созданию атмосферы отдыха, но главное, конечно, было на самой конференции. К сожалению, мне удалось поприсутствовать только на малой части докладов, т.к. дежурил в зоне экспертов, готовился к собственному докладу и т.д. Но главное, удалось побывать на всех докладах Скотта Хансельмана, и это было действительно очень здорово!&lt;br /&gt;
&lt;br /&gt;
Хансельман (&lt;a href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/a&gt;) – это один из самых выдающихся IT-докладчиков на сегодняшний день. Если вы еще не смотрели ВСЕ его доклады, очень рекомендую! Даже если вы не узнаете ничего нового (что невероятно, потому что Скотт очень любит собирать маленькие фишки о которых никто не знает), всегда стоит посмотреть Хансельмана. Это человек-театр, это зрелище которое просто нельзя пропускать.&lt;br /&gt;
&lt;br /&gt;
Более того, нам удалось пообщаться со Скоттом вживую (!!). На фотографии &lt;a href="http://gandjustas.blogspot.com/"&gt;Стас Выщепан&lt;/a&gt;, я и Скотт:&lt;br /&gt;
&lt;br /&gt;
&lt;img src="https://public.sn2.livefilestore.com/y1peZGyNSJtOw38YLlmmwXzfBmLvbt0XNh62Tykq4zSLL3NP5uUjoD0ihxPYnqPrKzttY-iC4M7XDU4u7zfcGL1ew/8d.jpg?psid=1" style="display: block; float: none; margin-left: auto; margin-right: auto;" /&gt;&lt;br /&gt;
Очень общительный человек, Скотт бродил среди участников и среди экспертов в перерывах между докладами, и с удовольствием вступал в любые дискуссии и отвечал на любые вопросы. Всегда старался помочь, в частности мне удалось обратить его внимание на проблему со &lt;a href="http://projects.nikhilk.net/ScriptSharp"&gt;Script#&lt;/a&gt; в SharePoint.&lt;br /&gt;
&lt;br /&gt;
Наверное хотя бы некоторые из вас знают, что &lt;a href="http://weblogs.asp.net/soever/archive/2009/10/20/sharepoint-2010-client-side-javascript-object-model-library-written-in-script.aspx"&gt;SharePoint Client Object Model написан на Script#&lt;/a&gt;? Возможно, кто-то из вас также пробовал писать на Script# самостоятельно, и знают, чего это стоит, написать wrapper для какой-нибудь более-менее серьезной библиотеки? Возникает естественный вопрос, а что мешает Microsoft’у частично открыть исходники SharePoint ClientOM (для создания wrapper’а Script# не требуется реализация, только определения методов/классов/свойств и т.д.), сделав тех, кому нравится Script#, ну ОЧЕНЬ счастливыми? :)&lt;br /&gt;
&lt;br /&gt;
Такой вопрос мы задали Скотту, и после того как он понял проблему, он тут же написал создателю Script#, которого зовут Nikhil Kothari. Я искренне надеюсь, что у этого обращения будут какие-то результаты, потому что те, кто хоть раз использовал Script# – знают, насколько это классный инструмент, и насколько проще с его помощью писать серьезные JavaScript-приложения.&lt;br /&gt;
&lt;br /&gt;
Также, мы говорили со Скоттом о &lt;a href="http://knockoutjs.com/"&gt;KnockOut&lt;/a&gt;. У меня есть некоторый опыт практической работы с KnockOut.js в SharePoint, и недавно я даже делал в Softline внутренний доклад “KnockOutJs в SharePoint”. На докладе я озвучивал проблему с атрибутом &lt;b&gt;data-bind&lt;/b&gt;, с которой столкнулся самолично. Этот атрибут, как известно, очень хитрый. Он может содержать простые биндинги, а может целые выражения. Сделать ошибку в этом атрибуте ничего не мешает: значение атрибута является не более чем строкой, и сообщения об ошибках далеко не всегда внятные. Более того, поскольку биндингов очень много разных, и далеко не все из них сразу срабатывают, то мы можем вообще не получить никакого сообщения об ошибке и ошибочный вариант может запросто уйти на продакшен. А когда ошибка просачивается к клиентам, это уж совсем ужасно…&lt;br /&gt;
&lt;br /&gt;
Ответ Скотта состоял из двух пунктов:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Microsoft не собирается делать интеллисенс или пре-компилятор для KnockOutJs или для других OpenSource-проектов, даже несмотря на то, что сейчас KnockOutJs поставляется вместе с ASP.Net MVC 4. Причина проста: это очень дорого и это очень сложно. В этом я со Скоттом полностью согласен: в свое время я писал интеллисенс для LUA, и сложилось впечатление, что это даже сложнее, чем написать с нуля компилятор LUA…  &lt;/li&gt;
&lt;li&gt;Как вариант решения проблемы, Скотт предложил написать расширение для Visual Studio, которое бы добавляло подсветку внутрь аттрибута data-bind. Причем он показал, что подобные расширения действительно можно написать, в качестве примера приведя Colorizer для Mustache Templating Engine, который был написан вроде как всего за одну ночь создателем этого движка, человеком по имени Mads Kristensen. Более подробно об этом можно &lt;a href="http://www.hanselman.com/blog/VisualStudio11ExpressForWebForFrontEndDevelopmentJavaScriptHTML5CSS3.aspx"&gt;почитать у Скотта в блоге&lt;/a&gt;. Подсветка Mustache-кода (с помощью vsix-расширения) выглядит вот так (картинка заимствована из блога Скотта):&lt;/li&gt;
&lt;/ol&gt;
&lt;img alt="A nice subtle mustache template" border="0" height="373" src="http://www.hanselman.com/blog/content/binary/Windows-Live-Writer/Using-Visual-Studio-11-Web-Express-Beta-_14839/mustache_0ec34a13-805a-4146-87f0-80a9a0799566.png" style="background-image: none; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="A nice subtle mustache template" width="627" /&gt;&lt;br /&gt;
По-моему, решение весьма достойное (как минимум, “it sucks less”, как говорит Скотт :)…), и по наличии времени, я обязательно попробую разобраться, как это делается. Все-таки, в некоторых разрезах, KnockOutJs сделан очень удачно, и существует много ситуаций, когда его применение &lt;b&gt;значительно&lt;/b&gt; облегчает жизнь разработчику.&lt;br /&gt;
&lt;br /&gt;
На этом, пожалуй, всё, всем желаю удачных надвигающихся выходных, и да.. MsDevCon’12 был супер!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-1735726176259856771?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/Sq4gTdRrJMo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/1735726176259856771/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/05/msdevcon12-sharepoint.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1735726176259856771?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1735726176259856771?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/Sq4gTdRrJMo/msdevcon12-sharepoint.html" title="Впечатления от MsDevCon’12 и пара интересностей о SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-MS-6wlxTn04/T79rZPE98vI/AAAAAAAABVQ/waITpwICRC4/s72-c/image_thumb%25255B5%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/05/msdevcon12-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ADRnw_fCp7ImA9WhVXEEU.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-279206961725686368</id><published>2012-04-10T20:46:00.001+04:00</published><updated>2012-04-10T22:16:17.244+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-10T22:16:17.244+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>HTML5 и SharePoint</title><content type="html">Провожу серию докладов в своем отделе. Чтобы определить самые интересные для коллег темы докладов, мы провели анонимное голосование:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-1Ebu6OGes6Y/T4Ri-eyxAUI/AAAAAAAABUQ/gLjjIUdSPIs/s1600/sessionTopics.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="256" src="http://2.bp.blogspot.com/-1Ebu6OGes6Y/T4Ri-eyxAUI/AAAAAAAABUQ/gLjjIUdSPIs/s400/sessionTopics.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
Результаты оказались довольно неожиданными для меня: со значительным отрывом победила тема "Общие сведения&amp;nbsp;по HTML5 и CSS3". В сочетании с другими предлагавшимися&amp;nbsp;темами, получилось, что 34% всех голосов были за HTML5.&lt;br /&gt;
&lt;br /&gt;
Поэтому, первым докладом в серии стал доклад "SharePoint и HTML5". Значительная часть доклада посвящена общему описанию: что такое HTML5, почему он вдруг потребовался, и какие основные возможности включает.&lt;br /&gt;
&lt;br /&gt;
Также, чтобы увеличить ценность доклада, при описании возможностей HTML5 я рассказываю о своем реальном опыте применения этих возможностей, и особенно об опыте применения HTML5 в SharePoint.&lt;br /&gt;
&lt;br /&gt;
Не смею больше томить, вот собственно доклад:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="344" src="http://www.youtube.com/embed/a4RZ-vmiALw?fs=1" width="459"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-279206961725686368?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/siSyZ2Sa30Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/279206961725686368/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/04/html5-sharepoint.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/279206961725686368?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/279206961725686368?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/siSyZ2Sa30Y/html5-sharepoint.html" title="HTML5 и SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-1Ebu6OGes6Y/T4Ri-eyxAUI/AAAAAAAABUQ/gLjjIUdSPIs/s72-c/sessionTopics.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/04/html5-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8EQXk-cSp7ImA9WhRaEkU.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-2836773937150296742</id><published>2012-02-15T09:30:00.000+04:00</published><updated>2012-02-15T09:30:00.759+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-15T09:30:00.759+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Scrum" /><title>Scrum в команде SharePoint</title><content type="html">Вчера завершился очередной спринт. По результатам: почти все задачи выполнены, большая часть из выполненных уже протестирована и закрыта, и ребята даже успели позаниматься парным программированием... :)&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-585affyOtEo/TzqFSRzdseI/AAAAAAAABOQ/3AsQ6O3t6Ig/s1600/burndown.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-585affyOtEo/TzqFSRzdseI/AAAAAAAABOQ/3AsQ6O3t6Ig/s1600/burndown.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
На самом деле, вот еще буквально полгода назад я думал что Scrum в команде, которая делает SharePoint, не очень актуален. Я считал, что из-за особенностей разработки под SharePoint, из-за того что мы фактически пишем кучу слабосвязанных плагинов, а не цельный продукт - командная разработка привносит больше вреда, чем пользы: это происходит из-за оверхеда на общение и организационные процедуры, которые вроде как никому особо и не нужны, т.к. каждый занят своим модулем и в чужие дела не лезет.&lt;br /&gt;
&lt;br /&gt;
Как вы уже наверное догадались, я ошибался. Причем, сильно ошибался...&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Итак, что же дает Scrum, что дает командная разработка и почему это применимо к SharePoint?&lt;br /&gt;
&lt;br /&gt;
Во-первых, я на самом деле не уверен, что созданные независимо модули могут магическим образом объединятся в удобный и цельный продукт. Нет, чудес на свете не бывает. Либо вы делаете модули отдельно, и потом получаете неказистую и неконкурентную штуковину, которую практически невозможно продать на современном рынке, либо вы уже изначально пишете цельный продукт - и тогда вещи начинают выглядеть совершенно иначе.&lt;br /&gt;
&lt;br /&gt;
Во-вторых, общение в команде, постоянные митинги и стэндапы - сначала это конечно непривычно и напрягает, ведь сроки поджимают и все такое, но если грамотно построить эти встречи, для каждой встречи ввести расписание, и не заставлять присутствовать тогда когда человека не касается обсуждение - это действительно начинает работать!&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-302HXludrR0/Tzq8vm_oR9I/AAAAAAAABOc/7OK-B1uC7yc/s1600/team_devel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-302HXludrR0/Tzq8vm_oR9I/AAAAAAAABOc/7OK-B1uC7yc/s1600/team_devel.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Встречи и обсуждения - это прежде всего, общение. И когда люди общаются, это само по себе уже благотворно влияет на атмосферу в коллективе: команда становится более дружной, угрюмые одиночки вдруг оказываются неплохими ребятами ну и всё такое. Человек существо социальное все-таки, даже разработчик :)&lt;br /&gt;
&lt;br /&gt;
Ну и конечно, деловое общение на разнообразных Scrum-собраниях - это обмен опытом, обмен идеями (brainstorming), активное отслеживание рисков и проблем, взаимопомощь. Всё это &lt;b&gt;сильно&lt;/b&gt; повышает эффективность и очень быстро окупается.&lt;br /&gt;
&lt;br /&gt;
С точки же зрения бизнеса, Scrum прежде всего дает предсказуемость. Реально работающую оценку трудозатрат, которая подтверждается из спринта в спринт. Вспомните, ведь любой проект начинается с вопроса: "За сколько ты сможешь это сделать?". И правильная оценка - безусловный залог стабильной прибыли и довольных клиентов.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-b6oGj-5sE0g/TzrGeDul8MI/AAAAAAAABOo/8l4pEZA9Wek/s1600/my_life_operates_in_a_predictable_cycle_krebs_tshirt-p235484809783928671qw9y_400.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-b6oGj-5sE0g/TzrGeDul8MI/AAAAAAAABOo/8l4pEZA9Wek/s1600/my_life_operates_in_a_predictable_cycle_krebs_tshirt-p235484809783928671qw9y_400.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Кстати, кто работал с оценками по SharePoint-проектам, те знают и понимают, что хороший estimation в SharePoint - это очень сложно. Влезли в стандартный функционал - задача решается за полдня. Не влезли - попали на месяц трудозатрат. И тем не менее, planning poker из спринта в спринт срабатывает, и это даже для SharePoint, и это даже несмотря на то, что наш Scrum на самом деле весьма далек от идеального Scrum'а. Как? Точно не знаю. Но работает :)&lt;br /&gt;
&lt;br /&gt;
В общем, на самом деле я лично очень доволен, и надеюсь наш отдел будет продолжать развиваться в том же духе :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-2836773937150296742?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/YqTHvLwTaqg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/2836773937150296742/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/02/scrum-sharepoint.html#comment-form" title="Комментарии: 6" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/2836773937150296742?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/2836773937150296742?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/YqTHvLwTaqg/scrum-sharepoint.html" title="Scrum в команде SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-585affyOtEo/TzqFSRzdseI/AAAAAAAABOQ/3AsQ6O3t6Ig/s72-c/burndown.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/02/scrum-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8HQ3Y5fip7ImA9WhRaEEk.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-8194408640361417651</id><published>2012-02-08T21:49:00.001+04:00</published><updated>2012-02-12T15:57:12.826+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-12T15:57:12.826+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Генерация большого числа записей в список SharePoint</title><content type="html">Генерация записей в список - это довольно частая задача, пригодится не только тестировщикам, но и программистам - всегда интересно проверить на практике ограничения списков, и насколько будет тормозить выборка/вставка/обработка данных при стольких-то записях в списке.&lt;br /&gt;
&lt;br /&gt;
Поэтому неплохо это уметь, а не уповать "на авось", тем более что делается это очень просто с помощью довольно короткого PowerShell-скрипта. У меня давно уже валяется такой скрипт, который использую лично я, вот решил поделиться :)&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Не смею больше тянуть:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span class="psComment"&gt;# Генерим XML для создания 150 записей в списке с GUID = $listID&lt;/span&gt;
&lt;span class="psComment"&gt;# Колонку с InternalName=$column заполняем случайными числами от 1 до 10 млн.&lt;/span&gt;
&lt;span class="psKeyword"&gt;function&lt;/span&gt; Generate150Items(&lt;span class="psVariable"&gt;$listID&lt;/span&gt;, &lt;span class="psVariable"&gt;$column&lt;/span&gt;)
{
  &lt;span class="psVariable"&gt;$method&lt;/span&gt; = &lt;span class="psString"&gt;"&amp;lt;Method ID="&lt;/span&gt;&lt;span class="psString"&gt;"{0}"&lt;/span&gt;&lt;span class="psString"&gt;"&amp;gt;&amp;lt;SetList&amp;gt;"&lt;/span&gt; + &lt;span class="psVariable"&gt;$listID&lt;/span&gt; + &lt;span class="psString"&gt;"&amp;lt;/SetList&amp;gt;&amp;lt;SetVar Name="&lt;/span&gt;&lt;span class="psString"&gt;"Cmd"&lt;/span&gt;&lt;span class="psString"&gt;"&amp;gt;Save&amp;lt;/SetVar&amp;gt;&amp;lt;SetVar Name="&lt;/span&gt;&lt;span class="psString"&gt;"ID"&lt;/span&gt;&lt;span class="psString"&gt;"&amp;gt;New&amp;lt;/SetVar&amp;gt;&amp;lt;SetVar Name="&lt;/span&gt;&lt;span class="psString"&gt;"urn:schemas-microsoft-com:office:office#"&lt;/span&gt; + &lt;span class="psVariable"&gt;$column&lt;/span&gt; + &lt;span class="psString"&gt;""&lt;/span&gt;&lt;span class="psString"&gt;"&amp;gt;{1}&amp;lt;/SetVar&amp;gt;&amp;lt;/Method&amp;gt;`n"&lt;/span&gt;
  Write-Host Method template: &lt;span class="psVariable"&gt;$method&lt;/span&gt;
  &lt;span class="psVariable"&gt;$methods&lt;/span&gt; = &lt;span class="psString"&gt;""&lt;/span&gt;
  &lt;span class="psVariable"&gt;$r&lt;/span&gt; = New-Object System.Random
  &lt;span class="psKeyword"&gt;for&lt;/span&gt;(&lt;span class="psVariable"&gt;$i&lt;/span&gt; = 1;&lt;span class="psVariable"&gt;$i&lt;/span&gt; &lt;span class="psOperator"&gt;-le&lt;/span&gt; 150; &lt;span class="psVariable"&gt;$i&lt;/span&gt;++)
  {
    &lt;span class="psVariable"&gt;$methods&lt;/span&gt; = &lt;span class="psVariable"&gt;$methods&lt;/span&gt; + [System.String]::Format(&lt;span class="psVariable"&gt;$method&lt;/span&gt;, &lt;span class="psVariable"&gt;$i&lt;/span&gt;, &lt;span class="psVariable"&gt;$r&lt;/span&gt;.Next(1,10000000))
  }
  &lt;span class="psKeyword"&gt;return&lt;/span&gt; [System.String]::Format(&lt;span class="psString"&gt;"&amp;lt;?xml version="&lt;/span&gt;&lt;span class="psString"&gt;"1.0"&lt;/span&gt;&lt;span class="psString"&gt;" encoding="&lt;/span&gt;&lt;span class="psString"&gt;"UTF-8"&lt;/span&gt;&lt;span class="psString"&gt;"?&amp;gt;&amp;lt;ows:Batch OnError="&lt;/span&gt;&lt;span class="psString"&gt;"Return"&lt;/span&gt;&lt;span class="psString"&gt;"&amp;gt;{0}&amp;lt;/ows:Batch&amp;gt;"&lt;/span&gt;, &lt;span class="psVariable"&gt;$methods&lt;/span&gt;);
  
}

&lt;span class="psComment"&gt;# Пример использования&lt;/span&gt;
&lt;span class="psVariable"&gt;$web&lt;/span&gt; = Get-SPWeb http://localhost
&lt;span class="psVariable"&gt;$list&lt;/span&gt; = &lt;span class="psVariable"&gt;$web&lt;/span&gt;.Lists[&lt;span class="psString"&gt;"Your list title"&lt;/span&gt;]
&lt;span class="psVariable"&gt;$xml&lt;/span&gt; = Generate150Items &lt;span class="psVariable"&gt;$list&lt;/span&gt;.ID &lt;span class="psString"&gt;"Title"&lt;/span&gt;
&lt;span class="psVariable"&gt;$results&lt;/span&gt; = &lt;span class="psVariable"&gt;$web&lt;/span&gt;.ProcessBatchData(&lt;span class="psVariable"&gt;$xml&lt;/span&gt;)&lt;/pre&gt;
&lt;br /&gt;
Результат:
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-s3MuTBQX1oY/TzKyh74iwrI/AAAAAAAABNY/4FpR_mkznPM/s1600/ps_add150.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-s3MuTBQX1oY/TzKyh74iwrI/AAAAAAAABNY/4FpR_mkznPM/s1600/ps_add150.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
В списке:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-8_k29EqqXY8/TzKzFk7fJYI/AAAAAAAABNk/wcwgcbMIMnA/s1600/list_150.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-8_k29EqqXY8/TzKzFk7fJYI/AAAAAAAABNk/wcwgcbMIMnA/s1600/list_150.png" /&gt;&lt;/a&gt;&lt;/div&gt;
P.S.: Да, желательно тестовые данные создавать в &lt;b&gt;тестовых&lt;/b&gt; списках, потому что удалить, к примеру, 15000 записей без удаления самого списка - на самом деле далеко не так просто, как это может показаться :)&lt;br /&gt;
&lt;br /&gt;
Но если вам все-таки нужно будет удалить много записей, и не удалять при этом список - как это сделать правильно, описано &lt;a href="http://sharepoint.stackexchange.com/questions/26542/deleting-all-the-items-from-a-large-list-in-sharepoint"&gt;на SharePoint StackExchange&lt;/a&gt; (к слову, это ответ многим известного &lt;a href="http://rusharepoint2010.blogspot.com/"&gt;Игоря Афанасова&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-8194408640361417651?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/3Xz8ymAgOVw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/8194408640361417651/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2012/02/sharepoint.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8194408640361417651?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8194408640361417651?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/3Xz8ymAgOVw/sharepoint.html" title="Генерация большого числа записей в список SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-s3MuTBQX1oY/TzKyh74iwrI/AAAAAAAABNY/4FpR_mkznPM/s72-c/ps_add150.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2012/02/sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYESH88eip7ImA9WhRSEU8.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-5198342321005622389</id><published>2011-11-08T08:03:00.000+04:00</published><updated>2011-11-12T23:28:29.172+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T23:28:29.172+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="Workflow" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Введение в рабочие процессы SharePoint 2010</title><content type="html">На мой взгляд, Workflow - это как раз та самая "магическая" субстанция, которая позволяет превратить безжизненную свалку данных в живую, рабочую систему - систему, которая рассылает письма, следит за сроками выполнения задач, и главное - всегда знает ответ на вопрос: "что с этим документом делать дальше?".
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-3lleHfZHDr8/TrhUBQZT3mI/AAAAAAAABEM/LzlroZU789w/s1600/sampleVisioWF.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-3lleHfZHDr8/TrhUBQZT3mI/AAAAAAAABEM/LzlroZU789w/s1600/sampleVisioWF.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Я считаю, что без понимания концепции рабочих процессов и их возможностей, - ваше знание SharePoint'а нельзя считать полным! И на мой взгляд, их действительно стоит изучать: они классные, и могут вам сэкономить немало дней, если их использовать с умом и по-назначению.&lt;br /&gt;
&lt;br /&gt;
Впрочем, как это всегда бывает в SharePoint, существует множество тонкостей, нюансов и особенностей, которые нужно знать и иметь в виду, прежде чем говорить клиенту/начальнику о том, что вот мол на решение этой задачи уйдет полдня :)&lt;br /&gt;
&lt;br /&gt;
Итак, давайте рассмотрим вкратце, что представляют собой рабочие процессы в SharePoint. Эта статья является стартовой в новой серии статей про рабочие процессы.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Практическое применение&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Рабочие процессы (Workflow) в SharePoint 2010 - это очень мощный и гибкий инструмент для организации совместной работы над документами и данными. Если говорить упрощенно, Workflows представляют собой алгоритм, т.е. набор правил и шагов, определяющих, какие действия будут предприняты над документом или элементом списка, после его добавления или обновления (плюс, можно запускать Workflow вручную или программно).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-zB5YTysxsO8/TrhZcJZZZ2I/AAAAAAAABEU/s6dNYjccYsI/s1600/issueCreated.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-zB5YTysxsO8/TrhZcJZZZ2I/AAAAAAAABEU/s6dNYjccYsI/s1600/issueCreated.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
С точки зрения программистов, рабочие процессы могут поначалу очень напоминать Event Receiver. Поэтому важно понимать - на самом деле они гораздо сложнее, чем Event Receiver, устроены совершенно иначе, и подразумевают, прежде всего:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Возможность длительного исполнения&lt;/li&gt;
&lt;li&gt;Возможность дополнительного взаимодействия с пользователями&lt;/li&gt;
&lt;/ol&gt;
Благодаря этим двум возможностям, рабочие процессы очень хорошо подходят для решения настоящих бизнес-задач и для моделирования настоящих бизнес-процессов взаимодействия между пользователями и отделами.&lt;br /&gt;
&lt;br /&gt;
Наконец, практический пример использования рабочих процессов: в компании Softline, где я работаю, у нас есть огромный внутрикорпоративный портал на SharePoint, где на основе Workflow работают, как минимум: заявки, системы единого окна и система разрешения внутренних проблем HelpDesk. Не раз пользовался - весьма удобно. А ведь этот портал создан администраторами, т.е. с минимумом программирования или вообще без него! И я видел специализированные системы - поверьте, некоторые и похуже с такими задачами справляются...
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Когда стоит, и когда не стоит использовать рабочие процессы?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Ответ на самом деле очень прост, и частично содержится в самом вопросе: если речь идет о бизнес-требованиях и моделировании бизнес-процессов - нужно использовать Workflow. Для более низкоуровневого функционала, с бизнесом непосредственно не связанного - лучше подойдут Event Receivers и Timer Jobs.&lt;br /&gt;
&lt;br /&gt;
Под бизнес-процессом здесь подразумевается прежде всего взаимодействие сотрудников, отделов, организация работы с клиентами, организация внутренней работы компании. Иными словами, это макро-задачи с точки зрения бизнеса.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Три типа рабочих процессов SharePoint 2010&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Рабочие процессы в SharePoint 2010 значительно обновились по сравнению с 2007 версией, и на текущий момент могут быть трех типов: Site Workflow, Reusable Workflow и List Workflow. Как нетрудно догадаться, эти типы отличаются друг от друга объектами, в контексте которых работает рабочий процесс.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-Uh32yZWtGzg/TrhjDP49AwI/AAAAAAAABEc/-3kgDeQOSUs/s1600/threeWFTypes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Uh32yZWtGzg/TrhjDP49AwI/AAAAAAAABEc/-3kgDeQOSUs/s1600/threeWFTypes.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Первый тип - Site Workflows - пригождается довольно редко, и рассматривать его в сегодняшнем посте я не буду. List Workflows мы тоже рассматривать не будем, это устаревший тип, пришедший из 2007го SharePoint'а. Вкратце, рабочие процессы этого вида присоединяются обязательно к уже созданному экземпляру списка. Таким образом, применение этих рабочих процессов очень ограничено, они не могут быть перенесены или использованы повторно и т.д.&lt;br /&gt;
&lt;br /&gt;
Итак, остаются только Reusable Workflows. При их создании вы должны выбрать тип содержимого, к которому прицеплять этот рабочий процесс. От этого выбора зависит, какие поля можно будет использовать при построении процесса в дизайнере (т.е. какими вообще данными можно будет в основном оперировать).&lt;br /&gt;
&lt;br /&gt;
Поскольку типы содержимого могут наследоваться друг от друга, можно выбрать базовый тип содержимого "All" - в этом случае ваш рабочий процесс можно будет использовать вообще в любом списке, но тогда он сможет оперировать только самыми простейшими колонками - Title, Created, Created By, Modified, Modified By...&lt;br /&gt;
&lt;br /&gt;
Впрочем, здесь есть важное уточнение: существуют так называемые Association Columns - это колонки, которые будут автоматически созданы в списке при присоединенни к нему Reusable-рабочего процесса. Но тут, опять же, важно понимать: эти колонки будут созданы в любом случае, даже если аналогичные колонки с теми же именами уже в этом списке существуют.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Три инструмента для создания рабочих процессов&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Для создания рабочих процессов, на текущий можно использовать аж целых три различных программных продукта, на любой вкус:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;div&gt;
Microsoft Visio&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;SharePoint Designer&lt;/li&gt;
&lt;li&gt;Visual Studio&lt;/li&gt;
&lt;/ol&gt;
При этом Microsoft Visio позволяет только нарисовать красивый "набросок" рабочего процесса, который потом нужно обязательно изменять в SharePoint Designer. Впрочем, для бизнес-пользователей такой вариант очень хорош: они могут нарисовать процесс не вдаваясь в детали, а дорабатывать его будет уже администратор, программист или IT-специалист.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-uXT2jf3eWfY/Trhn2qVxlQI/AAAAAAAABEs/akslVx4Ctr8/s1600/visioSharePointTemplate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-uXT2jf3eWfY/Trhn2qVxlQI/AAAAAAAABEs/akslVx4Ctr8/s1600/visioSharePointTemplate.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Плюс к тому, с помощью Visio, рабочие процессы могут быть визуализированы через веб-интерфейс. Это очень классная "фишка", которая позволяет отобразить диаграмму процесса на сайте SharePoint, причем уже выполненные шаги будут &lt;a href="http://blogs.msdn.com/blogfiles/visio/WindowsLiveWriter/SharePointWorkflowAuthoringinVisioPremiu_FE21/clip_image012_2.jpg"&gt;помечены галочками&lt;/a&gt;. На мой взгляд, это может служить прекрасным добавлением к каким-нибудь отчетам/dashboard'ам. Функция работает только в SharePoint Server 2010, при наличии запущенных &lt;a href="http://technet.microsoft.com/ru-ru/library/ee663485.aspx"&gt;Visio Services&lt;/a&gt;, и включенной галочке в свойствах рабочего процесса в SPD:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-W3l4dH2WaBs/TrhmXWiPXAI/AAAAAAAABEk/O6VME_z5v_o/s1600/showVisualizationStatus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-W3l4dH2WaBs/TrhmXWiPXAI/AAAAAAAABEk/O6VME_z5v_o/s1600/showVisualizationStatus.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
В общем, Visio скорее нужно рассматривать как некое приятное дополнение к SharePoint Designer, чем как самостоятельный инструмент для создания SharePoint Workflow.&lt;br /&gt;
&lt;br /&gt;
Так что давайте рассмотрим следующий инструмент - собственно SharePoint Designer. Его можно использовать и без Visio, он вполне самодостаточен. Вообще, на мой взгляд, SPD как средство для создания рабочих процессов - это лучший вариант, потому что:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;div&gt;
Визуальный редактор в SPD - очень приятный и интуитивно-понятный. К слову, намного лучше, чем был в SPD 2007.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;SPD-workflow - это единственный тип workflow, который работает в Sandbox и Office365&lt;/li&gt;
&lt;li&gt;Reusable workflows можно переносить между фермами и сайтами&lt;/li&gt;
&lt;li&gt;Можно разрабатывать программные расширения (собственные Actions) для SPD-редактора. Эти расширения развертываются на сайт, и потом SharePoint Designer при подгрузке списка Workflow с сайта заодно подгружает и расширения, сразу же соответствующим образом обновляя свой интерфейс. Эта фишка работает в том числе и для Sandboxed Solutions.&lt;/li&gt;
&lt;/ol&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-AlKcNwqMeyc/TrhrlLcHexI/AAAAAAAABE0/_JXMF2hYzmc/s1600/spd.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-AlKcNwqMeyc/TrhrlLcHexI/AAAAAAAABE0/_JXMF2hYzmc/s1600/spd.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Внешний вид дизайнера рабочих процессов SPD 2010&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Наконец, последний вариант, Visual Studio Workflows. Минусы:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;div&gt;
Функционально больших отличий от SPD нет. Конечно, у SPD-workflows есть ряд ограничений, но на практике, все они обходятся через использование программных расширений, дополнительных колонок, или дополнительных workflow.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Если попробовать реализовать один и тот же функционал средствами Visual Studio и средствами SPD - в Visual Studio это делается &lt;i&gt;&lt;b&gt;значительно&lt;/b&gt;&lt;/i&gt; дольше и сложнее.&lt;/li&gt;
&lt;li&gt;SharePoint Workflows в Visual Studio реализованы на основе Windows Workflow Foundation, которая сама по себе весьма глючная - а SharePoint туда еще добавляет немало "нюансов" :)&lt;/li&gt;
&lt;li&gt;Visual Studio Workflows даже теоретически не работают в Sandbox. В свете выхода Office365, мне кажется это очень актуально.&lt;/li&gt;
&lt;/ol&gt;
Конечно, Visual Studio гораздо более гибкий и всё такое, но такая низкоуровневая гибкость на практике пригождается редко, а вот разработку и поддержку значительно усложняет.&lt;br /&gt;
&lt;br /&gt;
Поэтому я стараюсь использовать SPD Workflows и писать для них Sandboxed Workflow Actions.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Заключение&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Надеюсь, этот краткий обзор помог обратить ваше внимание на рабочие процессы SharePoint 2010 и обозначил некоторые общие направления для дальнейшего изучения. Конечно, полностью описать систему в рамках статьи невозможно: рабочие процессы - это действительно мощная система, и понадобилась бы целая книга, чтобы подробно её описать. Кстати, такая книга уже есть, её написал Phil Wicklund, рекомендую: &lt;a href="http://www.manning.com/wicklund/"&gt;SharePoint 2010 Workflows In Action&lt;/a&gt; (на английском языке).&lt;br /&gt;
&lt;br /&gt;
В следующих постах серии мы рассмотрим создание Sandboxed Workflow Actions, примеры "боевых" рабочих процессов, способы обхода встроенных ограничений рабочих процессов SPD, и многое другое. Так что, если еще не подписались на RSS - &lt;a href="http://feeds.feedburner.com/omlin"&gt;уже пора&lt;/a&gt;! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-5198342321005622389?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/P07GmD2sTHg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/5198342321005622389/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/11/sharepoint-2010.html#comment-form" title="Комментарии: 17" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5198342321005622389?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/5198342321005622389?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/P07GmD2sTHg/sharepoint-2010.html" title="Введение в рабочие процессы SharePoint 2010" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-3lleHfZHDr8/TrhUBQZT3mI/AAAAAAAABEM/LzlroZU789w/s72-c/sampleVisioWF.png" height="72" width="72" /><thr:total>17</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/11/sharepoint-2010.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAMQngyfip7ImA9WhdaFko.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-8414269827105547709</id><published>2011-10-26T09:00:00.000+04:00</published><updated>2011-10-27T03:13:03.696+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-27T03:13:03.696+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>SharePoint и XSLT: преобразуем колонку в строку</title><content type="html">В посте &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt.html"&gt;про объединение двух колонок в одну&lt;/a&gt; я показывал на "боевом" примере про комментарий руководителя, как можно сэкономить место на странице и сделать представление более привлекательным, объединяя несколько колонок в одну. С помощью XSLT, мы производили вот такое преобразование:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-zpV8yckjAUk/TqcRR7jaWJI/AAAAAAAABBQ/yHo6u1DYjJk/s1600/scrn2columns.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="371" src="http://3.bp.blogspot.com/-zpV8yckjAUk/TqcRR7jaWJI/AAAAAAAABBQ/yHo6u1DYjJk/s640/scrn2columns.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Но как видите, всё равно в строке с комментарием остается много пустого места:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-P4TkyZtX4ZM/TqcSSVk7z_I/AAAAAAAABBY/MO-p6xDK1fE/s1600/blankspot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="136" src="http://4.bp.blogspot.com/-P4TkyZtX4ZM/TqcSSVk7z_I/AAAAAAAABBY/MO-p6xDK1fE/s640/blankspot.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Сегодня давайте попробуем расширить пример, вынеся комментарий вообще в отдельную строку, получив в финале примерно такой вид:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-7O4E_jftu98/Tqcjx5fbROI/AAAAAAAABB4/1IjigfElGj8/s1600/rowresult.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="188" src="http://2.bp.blogspot.com/-7O4E_jftu98/Tqcjx5fbROI/AAAAAAAABB4/1IjigfElGj8/s640/rowresult.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Вперед?&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Прежде всего, давайте вспомним теорию и упрощенное дерево шаблонов XsltListViewWebPart:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-RUFT6gSpZuE/TpXwdAxaBGI/AAAAAAAAA-E/HkvILWdLdv8/s1600/xlvtemplatetree.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-RUFT6gSpZuE/TpXwdAxaBGI/AAAAAAAAA-E/HkvILWdLdv8/s320/xlvtemplatetree.jpg" width="187" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
В предыдущем примере мы изменяли шаблон &lt;b&gt;PrintTableCellEcbAllowed&lt;/b&gt; у заголовочной ячейки, и помещали туда дополнительный &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;div&lt;/span&gt;&lt;/span&gt;, в который вставляли текст комментария руководителя. Легко догадаться, что в этот раз шаблон &lt;b&gt;PrintTableCellEcbAllowed&lt;/b&gt; нам не поможет: придется подниматься по дереву шаблонов вверх, и работать уже с шаблоном &lt;b&gt;Item&lt;/b&gt;, который, напомню, выводит элемент &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt; - то есть всю строку.&lt;br /&gt;
&lt;br /&gt;
Нам нужно всего лишь научить этот шаблон в некоторых случаях (когда &lt;b&gt;PM's comment&lt;/b&gt; не пустой) выводить два элемента &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt; вместо одного, и во второй &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt; вставлять тот же самый &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Признаюсь честно, для меня это преобразование выглядит элементарным, но судя по комментариям к посту про две колонки, не для всех это настолько очевидно... :) Поэтому давайте еще раз вкратце распишем алгоритм наших действий, требуемых для желаемого преобразования:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;div&gt;
Получить код стандартного шаблона &lt;b&gt;Item&lt;/b&gt;.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;div&gt;
Найти в этом коде завершающий тег &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;/span&gt;, и после него добавить условный вывод еще одного &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt;, содержащего уже известный нам по посту про объединение двух колонок &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
Получить код стандартного шаблона Item можно двумя способами.&lt;br /&gt;
&lt;br /&gt;
Во-первых, можно открыть в браузере на SharePoint-портале файл &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;/_layouts/xsl/vwstyles.xsl&lt;/span&gt;&lt;/span&gt;, и найти там шаблон &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;xsl:template mode="Item"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-EK5PGaKPkeg/TqcWYVMcX1I/AAAAAAAABBg/o7McjFt2MkY/s1600/vwstyles.xsl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-EK5PGaKPkeg/TqcWYVMcX1I/AAAAAAAABBg/o7McjFt2MkY/s1600/vwstyles.xsl.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Во-вторых, можно воспользоваться старым трюком с Conditional formatting, выбрав форматирование строки (а не столбца, как мы выбирали в прошлый раз):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-6c2oiS8V0gs/TqcXAxLeK9I/AAAAAAAABBo/0gS878hHPlE/s1600/formatrow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-6c2oiS8V0gs/TqcXAxLeK9I/AAAAAAAABBo/0gS878hHPlE/s1600/formatrow.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Далее нужно выбрать любое невыполнимое условие (например &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;ID='0'&lt;/span&gt;&lt;/span&gt;), и подключить любой стиль.&lt;br /&gt;
&lt;br /&gt;
В конечном итоге, всё равно получим в нашем теге &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;Xsl&amp;gt;&lt;/span&gt;&lt;/span&gt; шаблон &lt;b&gt;Item&lt;/b&gt;. Пролистываем до конца этого шаблона, видим закрывающий тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;/span&gt;. Ага, он-то нам и нужен!&lt;br /&gt;
&lt;br /&gt;
После него и перед &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;/xsl:template&amp;gt;&lt;/span&gt;&lt;/span&gt;, нужно добавить следующий код:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:if&lt;/span&gt; &lt;span style="color: red;"&gt;test&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$thisNode/@PM_x0027_s_x0020_comment != ''"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;tr&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;td&lt;/span&gt; &lt;span style="color: red;"&gt;colspan&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"{count($Fields)+1}"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;   &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;div&lt;/span&gt; &lt;span style="color: red;"&gt;style&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"background-color:#FFEEEE; margin: 5px; padding: 4px 10px; font-size: 9px;"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"../FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt; &lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"PrintFieldWithECB"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:with-param&lt;/span&gt; &lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"thisNode"&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$thisNode"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;    &lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;   &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;div&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;   &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;td&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;tr&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:if&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
На самом деле, я скопировал этот код из предыдущей статьи. Всё что я сделал здесь - это обернул &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;/span&gt; в &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt; и &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;/span&gt;, причем в &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;/span&gt; указал атрибут &lt;b&gt;colspan&lt;/b&gt;, чтобы расширить ячейку на всю строку.&lt;br /&gt;
&lt;br /&gt;
Переменная &lt;b&gt;$Fields&lt;/b&gt; - это список всех полей (FieldRef'ов), который передается шаблону &lt;b&gt;Item&lt;/b&gt; в качестве параметра. Плюс я использую стандартную xpath-функцию &lt;b&gt;count&lt;/b&gt; для подсчета количества полей.&lt;br /&gt;
&lt;br /&gt;
Если теперь переключиться во вкладку &lt;b&gt;Design&lt;/b&gt;, увидим, что ура, строка с нашим div'ом действительно появилась - но она почему-то пустая, в ней нет текста!&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-_wDdNQbw6V4/Tqca_9S8g3I/AAAAAAAABBw/gJVwN4wWOwQ/s1600/blankString.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-_wDdNQbw6V4/Tqca_9S8g3I/AAAAAAAABBw/gJVwN4wWOwQ/s1600/blankString.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Я специально допустил эту ошибку, и если вы читали статью про объединение двух колонок, вы должны легко найти причину ошибки сами, изучив повнимательнее код выше...&lt;br /&gt;
&lt;br /&gt;
Не удалось? Не страшно, ведь всегда можно подсмотреть правильный ответ&amp;nbsp;:)&lt;br /&gt;
&lt;br /&gt;
Дело здесь в том, что мы вызываем шаблон &lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;PrintFieldWithECB&lt;/span&gt;&lt;/span&gt; для неверной выборки данных. Ведь раньше мы вызывали его из другого шаблона, а сейчас шаблон изменился, и естественно, что нужно обновить xpath-запрос. Правильным решением здесь будет просто заменить &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;../FieldRef&lt;/span&gt;&lt;/span&gt; на &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;$Fields&lt;/span&gt;&lt;/span&gt; в xpath-запросе атрибута &lt;b&gt;select&lt;/b&gt; элемента &lt;b&gt;apply-templates&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;
На самом деле, я надеюсь, эту загадку вы легко разгадали, и получили то, что требовалось. Да, чтобы "догнать" внешний вид до скриншота в начале статьи, понадобится конечно немножко поиграться с css :)&lt;br /&gt;
&lt;br /&gt;
В следующей статье будет рассмотрен уже более серьезный пример. А в комментариях к этой статье, желающие могут изложить свои собственные задачки, и если они мне покажутся интересными и часто возникающими - я напишу про их решение отдельный пост.&lt;br /&gt;
&lt;br /&gt;
До новых встреч!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-8414269827105547709?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/NftkLc5vtAw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/8414269827105547709/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-xslt_26.html#comment-form" title="Комментарии: 9" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8414269827105547709?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8414269827105547709?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/NftkLc5vtAw/sharepoint-xslt_26.html" title="SharePoint и XSLT: преобразуем колонку в строку" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-zpV8yckjAUk/TqcRR7jaWJI/AAAAAAAABBQ/yHo6u1DYjJk/s72-c/scrn2columns.png" height="72" width="72" /><thr:total>9</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-xslt_26.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4EQX06fip7ImA9WhdaFUw.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-6642095303605827858</id><published>2011-10-25T08:45:00.000+04:00</published><updated>2011-10-25T08:45:00.316+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T08:45:00.316+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>SharePoint и XSLT: Развертывание через Visual Studio</title><content type="html">&lt;a href="http://1.bp.blogspot.com/-7mVDxbUWiAM/TqWdy5WyWZI/AAAAAAAABA0/ipZ-lIPHfFw/s1600/visualstudio.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="234" src="http://1.bp.blogspot.com/-7mVDxbUWiAM/TqWdy5WyWZI/AAAAAAAABA0/ipZ-lIPHfFw/s320/visualstudio.jpg" width="320" /&gt;&lt;/a&gt;К настоящему времени, в рамках серии статей про SharePoint и XSLT, уже были освещены многие интересные моменты, включая довольно актуальные примеры (разбор еще множества примеров - впереди), но до сих пор мы не касались развертывания XSL-преобразований через Visual Studio. Эта информация очень важна для разработчиков SharePoint, но замечу еще раз - что посредством SharePoint Designer, XSL-преобразованиями в SharePoint могут пользоваться и администраторы, и дизайнеры, и ITPro.&lt;br /&gt;
&lt;br /&gt;
Итак, сегодня мы узнаем:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Как подключать XSLT через CAML&lt;/li&gt;
&lt;li&gt;Как программно подключить XSL-преобразование к списку&lt;/li&gt;
&lt;li&gt;Чем отличаются свойства XslLink классов SPView и XsltListViewWebPart&lt;/li&gt;
&lt;li&gt;Ограничения при использовании XSLT в Sandboxed solutions&lt;/li&gt;
&lt;/ol&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span style="font-size: large;"&gt;Способы подключения XSLT&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Как всегда, SharePoint предоставляет множество различных возможностей для работы с XSLT через Visual Studio. Например, мы можем подключать XSL-преобразования как к представлениям списков, так и непосредственно к веб-частям XsltListViewWebPart; делать это через CAML или через объектную модель; разворачивать XSLT-файлы в SharePoint Mapped Folders или в библиотеки документов.&lt;br /&gt;
&lt;br /&gt;
Очень важно знать разницу между всеми этими способами - а она, поверьте, есть. И иногда она огромная.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Через CAML&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
К слову сказать, Collaborative Application Markup Language, в просторечии CAML - это вся совокупность XML-схем, которые могут быть использованы в целях расширения или настройки SharePoint'а. И если кто-то до сих пор думает, что CAML - это только схема Query, предназначенная для формирования запросов к спискам - нет, это не так, и вы легко можете в этом убедиться, внимательно почитав MSDN.&lt;br /&gt;
&lt;br /&gt;
В общем, все эти модули, Elements.xml, List Batch API - это всё CAML. Это очень мощная и развитая система, хотя и не всегда удобная. Кстати, не так давно я написал отдельную статью о том, &lt;a href="http://omlin.blogspot.com/2011/09/caml-sharepoint.html"&gt;почему CAML в SharePoint - это плохо&lt;/a&gt;, и когда следует опасаться его использовать.&lt;br /&gt;
&lt;br /&gt;
Если вернуться к нашим "баранам", CAML позволяет развертывать XSL-преобразования двумя способами:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Подключением к создаваемому шаблону списка&lt;/li&gt;
&lt;li&gt;Подключением к разворачиваемой веб-части XsltListViewWebPart&lt;/li&gt;
&lt;/ol&gt;
Как видите, нет возможности подключить XSLT к представлению существующего списка, точно также, как нет возможности подключить XSLT к уже существующей веб-части. Это довольно существенное ограничение, которое нужно понимать и иметь в виду.&lt;br /&gt;
&lt;br /&gt;
Но давайте посмотрим наконец, как это делается!&lt;br /&gt;
&lt;br /&gt;
Для подключения XSLT-файла нужно, прежде всего, создать сам XSLT-файл и развернуть его, чтобы обеспечить его доступность из SharePoint. Для этой цели, я создал SharePoint Mapped Folder "Layouts", в нем - папку проекта, и в ней - файл &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;HelloWorld.xsl&lt;/span&gt;&lt;/span&gt;, код для которого взял из статьи &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html"&gt;SharePoint и XSLT: Hello world!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Подключение к создаваемому шаблону списка&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Следующий шаг - создать новый элемент List Definition, на основе любого существующего шаблона списка:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-VvsntUwEuqo/TqWcGjx9f3I/AAAAAAAABAs/NYfCD5WOzfM/s1600/listDefinition.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-VvsntUwEuqo/TqWcGjx9f3I/AAAAAAAABAs/NYfCD5WOzfM/s1600/listDefinition.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Теперь откроем файл Schema.xml и пролистаем до списка представлений (элемент &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;Views&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;), найдем представление "по умолчанию" (&lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;DefaultView="TRUE"&lt;/span&gt;&lt;/span&gt;), и найдем в нем элемент &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;XslLink&amp;gt;&lt;/span&gt;&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-WUyu1VR9mbY/TqWFFRKz0hI/AAAAAAAABAk/BZy_pGhHFHw/s1600/xsllink.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-WUyu1VR9mbY/TqWFFRKz0hI/AAAAAAAABAk/BZy_pGhHFHw/s1600/xsllink.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Как видите, по умолчанию, в качестве файла с XSL-преобразованием указан файл &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;main.xsl&lt;/span&gt;&lt;/span&gt;. Естественно, можно его подменить. Но как указать на наш файл &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;HelloWorld.xsl&lt;/span&gt;&lt;/span&gt;?&lt;br /&gt;
&lt;br /&gt;
Поскольку файл &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;main.xsl&lt;/span&gt;&lt;/span&gt; лежит по пути &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;14\TEMPLATE\LAYOUTS\XSL&lt;/span&gt;&lt;/span&gt;, то очевидно, что нам нужно указать путь &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #93c47d;"&gt;..\SharePointXslt\HelloWorld.xsl&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (SharePointXslt - это название проекта). Обратите внимание: элемент XslLink принимает путь к файлу, а не Url. Попробовав указать Url в любом варианте, мы непременно получим ошибку. Таким образом, к элементу &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;View&amp;gt;&lt;/span&gt;&lt;/span&gt; никаким образом нельзя подключить XSLT-файл, размещенный в библиотеке документов! Поскольку элемент &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;View&amp;gt;&lt;/span&gt;&lt;/span&gt; в объектной модели представляется объектом SPView, то и для него это справедливо.&lt;br /&gt;
&lt;br /&gt;
Итак, получается, что через шаблон списка, мы сможем подключить только файл, расположенный в пределах 14 hive. Но означает ли это, что мы не можем подключать XSLT-файлы к шаблонам списков в Sandboxed Solutions? Вроде бы да: ведь SharePoint Mapped Folder в песочнице не работает!&lt;br /&gt;
&lt;br /&gt;
Но решение есть! Оно довольно хитрое, и я сомневаюсь, что даже самые опытные из читателей знают это. Так что вот вам сакральные знания:&lt;br /&gt;
&lt;blockquote align="center"&gt;
&lt;span style="font-size: large;"&gt;&lt;i&gt;&lt;b&gt;&lt;span style="background-color: orange;"&gt;&lt;span style="background-color: white;"&gt;&lt;span style="color: #990000;"&gt;Xsl-файл можно цеплять из папки фичи!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/blockquote&gt;
Как известно, в песочнице можно разворачивать модули (элемент проекта &lt;b&gt;Module&lt;/b&gt;). Файлы модулей традиционно сначала попадают в папку возможности (Feature), а уже потом загружаются в нужную библиотеку документов. И если указать путь к файлу модуля в фиче, относительно каталога, где лежит стандартный main.xsl, то это, как ни смешно, сработает :)&lt;br /&gt;
&lt;br /&gt;
При этом, внутренности Elements.xml можно удалить: ни в какую библиотеку документов файл загружать нет необходимости.&lt;br /&gt;
&lt;br /&gt;
Этот же трюк работает с программным заданием свойства SPView.XslLink.&lt;br /&gt;
&lt;br /&gt;
Прошу обратить внимание на то, что это всё-таки трюк, и в одном из следующих обновлений его теоретически могут даже исправить, введя какое-нибудь security-ограничение. Вероятность крайне мала, но есть.&lt;br /&gt;
&lt;br /&gt;
Поэтому, наверное, всё-таки лучше пойти более простым путем, и напрямую вписывать XSLT-код в тег &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;Xsl&amp;gt;&lt;/span&gt;&lt;/span&gt;. Этого тега по умолчанию в Schema.xml вы не найдете, но его можно легко добавить вместо &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;XslLink&amp;gt;&lt;/span&gt;&lt;/span&gt;. С этим подходом всё очень очевидно, надеюсь, сложностей здесь у ни у кого не возникнет.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Подключение к разворачиваемой веб-части&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Второй CAML-вариант - это присоединение XslLink к разворачиваемой веб-части XsltListViewWebPart. Веб-часть эта может быть легко развернута с помощью тега &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;AllUsersWebPart&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Стандартная последовательность действий в этом случае следующая:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Идем в нужный нам список (на страницу &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;AllItems.aspx&lt;/span&gt;&lt;/span&gt;), переключаем страницу в режим редактирования (Действия сайта -&amp;gt; Редактировать страницу), и в контекстном меню представления списка выбираем Экспорт веб-части:
&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-0rInWjiUaVc/TqWigLpdrzI/AAAAAAAABA8/viXwgsabxsM/s1600/exportWebPart.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-0rInWjiUaVc/TqWigLpdrzI/AAAAAAAABA8/viXwgsabxsM/s1600/exportWebPart.png" /&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;В результате, получаем xml-файл с расширением webpart, начинающийся тегом &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;webParts&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;В наш проект в Visual Studio, добавляем новый модуль (Module).&lt;/li&gt;
&lt;li&gt;Удаляем из модуля Sample.txt.&lt;/li&gt;
&lt;li&gt;Добавляем существующий элемент, в появившемся диалоге указываем какой-нибудь файл веб-частей, например, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\SiteTemplates\sts\default.aspx&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Переходим в Elements.xml, создаем внутри тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;File&amp;gt;&lt;/span&gt;&lt;/span&gt; тег &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;AllUsersWebPart&amp;gt;&lt;/span&gt;&lt;/span&gt;, прописывая в нем положение нашей веб-части на странице, и внутрь тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;AllUsersWebPart&amp;gt;&lt;/span&gt;&lt;/span&gt; наконец уже вставляем экспортированный xml из webpart-файла, заключив, естественно, его предварительно в CDATA:&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;AllUsersWebPart&lt;/span&gt; &lt;span style="color: red;"&gt;WebPartZoneID&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"Left"&lt;/span&gt; &lt;span style="color: red;"&gt;WebPartOrder&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"1"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;![CDATA[&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;webParts&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;!-- ... --&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/webParts&amp;gt;
&lt;span style="color: blue;"&gt;]]&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;AllUsersWebPart&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
В общем, в итоге получим довольно длинный файл Elements.xml, с тегами Module -&amp;gt; File -&amp;gt; AllUsersWebPart. Эта конструкция развернет страницу default.aspx и добавит на неё веб-часть.&lt;br /&gt;
&lt;br /&gt;
Соответственно, внутри тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;webParts&amp;gt;&lt;/span&gt;&lt;/span&gt; сложно не заметить теги &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;property&amp;gt;&lt;/span&gt;&lt;/span&gt;, которые как раз могут быть использованы для изменения свойств Xsl и XslLink объекта XsltListViewWebPart.&lt;br /&gt;
&lt;br /&gt;
Кстати, в отличие от тега XslLink в элементе View, тег XslLink в XsltListViewWebPart принимает как раз Url'ы. То есть, можно указывать на библиотеки документов.&lt;br /&gt;
&lt;br /&gt;
Однако, и здесь не обошлось без неприятностей :-( Оказывается, есть довольно серьезный "known bug", который не позволяет спокойно использовать подключение XSL-преобразований через свойство XslLink. Я писал об этом подробно &lt;a href="http://amarkeev.wordpress.com/2011/09/10/xsllink-issue/"&gt;в английском блоге&lt;/a&gt;, если вкратце: перестает работать контекстное меню элементов списка, а также перестают работать кнопки "Изменить элемент", "Просмотреть элемент" и "Удалить" на ленте.&lt;br /&gt;
&lt;br /&gt;
Баг возникает только при использовании xsl-файлов из библиотек документов. В случае с файлами, развернутыми в _layouts - все работает прекрасно. Но как сами понимаете, для того чтобы развернуть файлы в _layouts, нужны полномочия администратора фермы...&lt;br /&gt;
&lt;br /&gt;
А с библиотеками документов, да, баг очень серьезный. Он возникает не на всех компьютерах, но мне удалось его воспроизвести как минимум на пяти совершенно разных машинах, и на русском, и на английском SharePoint, и даже на двух аккаунтах Office365. Есть даже &lt;a href="http://social.msdn.microsoft.com/Forums/en/sharepoint2010general/thread/c7f07596-cb45-49fe-ba0f-88faa5fb981d"&gt;ответ от парня из Microsoft&lt;/a&gt;, о том, что они об этом баге знают, и над ним работают...&lt;br /&gt;
&lt;br /&gt;
В итоге, опять же приходим к тому, что лучше всегда использовать тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;lt;Xsl&amp;gt;&lt;/span&gt;&lt;/span&gt; и прописывать преобразования напрямую в код внутри &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;AllUsersWebPart&lt;/span&gt;&lt;/span&gt;. И выглядеть это, поверьте мне на слово, будет очень убого (потому что двойной CDATA сделать нельзя, и придется эскейпить "по старинке", через &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;&amp;amp;lt;&lt;/span&gt;&lt;/span&gt; и &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;amp;gt;&lt;/span&gt;&lt;/span&gt;)... :-(&lt;br /&gt;
&lt;br /&gt;
Кстати, для того, чтобы использовать созданное Xslt-преобразование списка много раз, имеет смысл не пользоваться тегом AllUsersWebPart, а развернуть "преднастроенный" webpart-файл в галерею веб-частей. Тогда пользователи сами смогут добавлять эту веб-часть на нужные им страницы. Проблема абсолютной нечитаемости XSLT-кода остается, но в случае Sandboxed Solutions этот вариант вас, возможно, просто-таки спасет...&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Программное подключение XSL-преобразований&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
Основное отличие программного развертывания от развертывания через CAML заключается в том, что программно мы можем не только создавать новые веб-части или представления списков - но также мы можем работать с уже существующими списками, представлениями, веб-частями. Это очень полезно и здорово, но есть и минусы.&lt;br /&gt;
&lt;br /&gt;
Дело в том, что программный подход как минимум намного более урезан в Sandboxed Solutions. Например, веб-части недоступны из объектной модели в песочнице, также запрещен и класс SPLimitedWebPartManager. То есть работать с XsltListViewWebPart не получится совсем.&lt;br /&gt;
&lt;br /&gt;
Впрочем, когда можно работать с SPView, опускаться до уровня веб-частей обычно и не требуется.&lt;br /&gt;
&lt;br /&gt;
Но и c SPView тоже не все так просто. Есть неприятный баг, на этот раз, как раз при использовании свойства Xsl. Если вкратце - использовать это свойство невозможно :)&lt;br /&gt;
&lt;br /&gt;
В результате какого-то внутреннего преобразования, при присваивании этого свойства осуществляется обработка входящего xsl-кода, в результате чего пропадают префиксы &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;xsl:&lt;/span&gt;&lt;/span&gt;. При этом преобразование само по себе, как я понимаю, остается в принципе вполне рабочим - но тут в действие вступает фактор номер два! При загрузке XSL-преобразования уже в момент отображения представления списка, происходит валидация сохраненного ранее XSL, и валидация эта требует присутствия префикса... #fail&lt;br /&gt;
&lt;br /&gt;
Никакие обманные пути не помогают: в свое время, убил порядка 4 часов на попытки обойти эту проблему. Так что SPView.Xsl лучше не пытаться использовать. Не получится :(&lt;br /&gt;
&lt;br /&gt;
Таким образом, для Sandbox, остается только хитрый способ с подключением XSLT-файла из папки фичи, который я описывал выше.&lt;br /&gt;
&lt;br /&gt;
Для farm-solutions все проще: есть возможность использовать XsltListViewWebPart, и есть возможность развертывать XSL-файлы в &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;_layouts&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Программное подключение XSLT к представлениям списка&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Давайте теперь посмотрим код:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FeatureActivated(&lt;span style="color: #2b91af;"&gt;SPFeatureReceiverProperties&lt;/span&gt; properties)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; web = properties.Feature.Parent &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPWeb&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = web.Lists[&lt;span style="color: #a31515;"&gt;"Test"&lt;/span&gt;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; view = list.DefaultView;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.XslLink = &lt;span style="color: #a31515;"&gt;@"..\..\FEATURES\SandboxTest_Feature1\XsltModule\Sample.xsl"&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.Update();
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Да, в основном такие вещи осуществляются в Feature Receiver, но хочу сразу же заметить, что забивать класс Feature Event Receiver простынями кода - вообще говоря нехорошо. Если у вас там планируется много кода, сразу разбивайте его на классы.&lt;br /&gt;
&lt;br /&gt;
А в представленном выше примере, между прочим, как раз тот самый трюк с подхватыванием XSLT из папки фичи, про который я говорил. &lt;br /&gt;
&lt;br /&gt;
Как видите, всё довольно просто: получаем какой-то существующий список (с заголовком Test), и подключаем к его представлению "по умолчанию" существующий в папке фичи файл. Сам файл изначально лежит в модуле:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-E6JfSbqXS60/TqW2AKjahmI/AAAAAAAABBE/AhkLrdAv4C8/s1600/SandboxTestProject.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-E6JfSbqXS60/TqW2AKjahmI/AAAAAAAABBE/AhkLrdAv4C8/s1600/SandboxTestProject.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Важный момент! Вот такой вот код, выглядящий вроде аналогичным представленному выше:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FeatureActivated(&lt;span style="color: #2b91af;"&gt;SPFeatureReceiverProperties&lt;/span&gt; properties)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; web = properties.Feature.Parent &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPWeb&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = web.Lists[&lt;span style="color: #a31515;"&gt;"Test"&lt;/span&gt;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="background-color: #ea9999;"&gt;list.DefaultView&lt;/span&gt;.XslLink = &lt;span style="color: #a31515;"&gt;@"..\..\FEATURES\SandboxTest_Feature1\XsltModule\Sample.xsl"&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="background-color: #ea9999;"&gt;list.DefaultView&lt;/span&gt;.Update();
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
...&lt;b&gt;работать не будет!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Дело в том, что DefaultView всегда создает новый экземпляр объекта, и поэтому list.DefaultView.Update() будет пытаться сохранить только что созданный, неизмененный объект... Более подробно можно почитать в &lt;a href="https://plus.google.com/102947712850220163334/posts/4Eg6icsZLJG"&gt;посте Антона Вишнякова&lt;/a&gt;.
&amp;nbsp;В общем, будьте аккуратны: на эту ошибку напарываются довольно часто.&lt;br /&gt;
&lt;br /&gt;
Для farm solutions, подключение XSLT-файлов работает аналогичным образом. Для обсуждавшегося в начале статьи файла &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;HelloWorld.xsl&lt;/span&gt;&lt;/span&gt;, код будет выглядеть следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FeatureActivated(&lt;span style="color: #2b91af;"&gt;SPFeatureReceiverProperties&lt;/span&gt; properties)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; web = properties.Feature.Parent &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPWeb&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = &lt;span style="background-color: #ea9999;"&gt;web.Lists&lt;/span&gt;[&lt;span style="color: #a31515;"&gt;"Test"&lt;/span&gt;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; view = list.DefaultView;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.XslLink = &lt;span style="color: #a31515;"&gt;@"..\SharePointXslt\HelloWorld.xsl"&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.Update();
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Да, еще один момент: получать список по заголовку не очень хорошо. Заголовок ведь кто угодно может изменить, поэтому более надежный способ - это метод &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.getlistfromwebpartpageurl.aspx"&gt;GetListFromWebPartPageUrl&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Код изменится следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FeatureActivated(&lt;span style="color: #2b91af;"&gt;SPFeatureReceiverProperties&lt;/span&gt; properties)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; web = properties.Feature.Parent &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPWeb&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = web.GetListFromWebPartPageUrl(&lt;span style="color: #a31515;"&gt;"Lists/Test/AllItems.aspx"&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; view = list.DefaultView;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.XslLink = &lt;span style="color: #a31515;"&gt;@"..\SharePointXslt\HelloWorld.xsl"&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;view.Update();
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Программное подключение XSLT к веб-частям&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Здесь тоже ничего сложного нет, главное - не забывать освобождать использованные объекты :)&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; FeatureActivated(&lt;span style="color: #2b91af;"&gt;SPFeatureReceiverProperties&lt;/span&gt; properties)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; web = properties.Feature.Parent &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPWeb&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = web.Lists[&lt;span style="color: #a31515;"&gt;"Test"&lt;/span&gt;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;using&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;SPLimitedWebPartManager&lt;/span&gt; manager = web.GetLimitedWebPartManager(list.DefaultViewUrl, &lt;span style="color: #2b91af;"&gt;PersonalizationScope&lt;/span&gt;.Shared))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;var&lt;/span&gt; xlv = (manager.WebParts[0] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;XsltListViewWebPart&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xlv.XslLink = &lt;span style="color: #a31515;"&gt;"/_layouts/SharePointXslt/HelloWorld.xsl"&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;manager.SaveChanges(xlv);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
В этом примере мы изменяем страницу представления "по умолчанию" списка. Стоит отметить, что поскольку XsltListViewWebPart - это непосредственно веб-часть, которая осуществляет отображение списка, а SPView - это более абстрактный объект, то если изменить XsltListViewWebPart, то она как бы "отцепится" от своего представления, и дальнейшие изменения SPView не будут иметь эффекта.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Подводя итоги&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Сегодня мы рассмотрели способы развертывания XSLT и присоединения преобразований к спискам и веб-частям. Уверен, что наиболее внимательные из читателей теперь смогут перечислить все эти способы и указать отличия между ними - когда лучше использовать один, а когда - другой. Одинаковых по эффекту способов, повторюсь, нет - каждый немного отличается от соседа.&lt;br /&gt;
&lt;br /&gt;
Кроме перечисления способов и обсуждения отличий между ними, мы сегодня рассмотрели очень много ошибок и нюансов, и я искренне надеюсь, что эта информация поможет вам сэкономить немало времени на борьбу с, как всегда, сложноуловимыми багами SharePoint'а :)&lt;br /&gt;
&lt;br /&gt;
Да, как всегда, если вам понравилась статья, не забудьте &lt;a href="http://feeds.feedburner.com/omlin"&gt;подписаться на мой блог&lt;/a&gt;! :) Любые комментарии приветствуются.&lt;br /&gt;
&lt;br /&gt;
P.S. В следующей статье серии мы вернемся к рассмотрению "боевых" примеров использования XSLT.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-6642095303605827858?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/nUclO964-kA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/6642095303605827858/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-visual-studio.html#comment-form" title="Комментарии: 6" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6642095303605827858?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6642095303605827858?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/nUclO964-kA/sharepoint-xslt-visual-studio.html" title="SharePoint и XSLT: Развертывание через Visual Studio" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-7mVDxbUWiAM/TqWdy5WyWZI/AAAAAAAABA0/ipZ-lIPHfFw/s72-c/visualstudio.jpg" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-xslt-visual-studio.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UER3o-fSp7ImA9WhdbGU4.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-4608676882111219405</id><published>2011-10-18T16:00:00.000+04:00</published><updated>2011-10-18T16:00:06.455+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-18T16:00:06.455+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>Про XSLT и Visual Studio: отладка и intellisense</title><content type="html">По результатам публикации статьи &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html"&gt;SharePoint и XSLT: Hello world!&lt;/a&gt;, уже появились недовольные читатели, восклицающие в комментариях, что вот мол, использовать Блокнот/SharePoint Designer это непрофессионально... :) Примерно такие же отзывы я слышал и на RUSUG, где недавно читал доклад "SharePoint и XSLT".&lt;br /&gt;
&lt;br /&gt;
И на самом деле я согласен, что будучи разработчиком, и имея такой мощный и многофункциональный инструмент, как Visual Studio, хотелось бы использовать его богатые возможности для работы с XSLT в SharePoint. Точнее, хотя бы попробовать это сделать :))&lt;br /&gt;
&lt;br /&gt;
Ну вот давайте посмотрим, на что способна (или не способна?) Visual Studio.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span style="font-size: large;"&gt;Intellisense&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Вот вроде как, "Подумаешь, XSLT intellisense в Visual Studio настроить. Легко!". Легко, да не совсем! Во-первых, в редакторе XSLT в студии просто нет интеллисенса для XPath. Во-вторых, нет xsd-схем для SharePoint'овских расширений XSLT. В свое время, потратил целый день, пытаясь найти хоть какие-нибудь XSD - безрезультатно. Те, которые лежат в каталоге 14\TEMPLATE\XML, не подходят.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-iElEcHb2diE/TpsFQGXyrfI/AAAAAAAABAA/PrUMgxZaJC0/s1600/vserrors.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-iElEcHb2diE/TpsFQGXyrfI/AAAAAAAABAA/PrUMgxZaJC0/s1600/vserrors.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Так что в плане intellisense, максимум что мы получим в Visual Studio - это автоподстановки и подсказки по стандартной схеме XSLT. Всё. #fail&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-6kf7ANUufFk/TpsDsZ8ZQzI/AAAAAAAAA_4/zjHJCwEP71o/s1600/vsintellisense.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-6kf7ANUufFk/TpsDsZ8ZQzI/AAAAAAAAA_4/zjHJCwEP71o/s1600/vsintellisense.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
SharePoint Designer в этом отношении на 5 корпусов впереди: в нем есть довольно продвинутый intellisense для XPath, поддерживается значительная часть тегов расширения, причем никакого ручного подключения файлов входных данных не требуется - они автоматически подхватываются из веб-части, для которой осуществляется редактирование тэга &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;Xsl&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-Qnu-NJLVQRk/TpsDVUl39aI/AAAAAAAAA_w/3W0o2hB-wDw/s1600/spdintellisense.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-Qnu-NJLVQRk/TpsDVUl39aI/AAAAAAAAA_w/3W0o2hB-wDw/s1600/spdintellisense.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Отладка&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Ок, но хотя бы отладку XSLT можно запустить из студии!? Уж в этом-то студия не должна подвести!&lt;br /&gt;
&lt;br /&gt;
Но и здесь нас ждет некоторое огорчение. Во-первых, схемы XSLT в SharePoint'е весьма сложные, и требуют огромное количество параметров для нормальной работы. Следовательно, через GUI-редактор уже никакой отладки сразу же не получается.&lt;br /&gt;
&lt;br /&gt;
Впрочем, есть другой вариант: отладка через отдельное консольное приложение, через объект XslCompiledTransform. Если в &lt;a href="http://msdn.microsoft.com/en-us/library/ms163418.aspx"&gt;конструкторе&lt;/a&gt; этого объекта указать параметр true, то это будет означать специальный отладочный режим. И тогда при нажатии F11 на строке вызова метода Transform, можно попасть в XSLT-файл, и типа всё будет "чики-поки".&lt;br /&gt;
&lt;br /&gt;
Конечно, перед началом работы придется сдампить параметры преобразования и входной XML (&lt;em&gt;dsQueryResponse&lt;/em&gt;), и потом подпихнуть их в XslCompiledTransform. Это немало работы, но она разовая, поэтому того стоит.&lt;br /&gt;
&lt;br /&gt;
НО!&lt;br /&gt;
&lt;br /&gt;
Есть еще ddwrt-функции и всякие ddwrt-атрибуты. Они подключаются через Extension Object. Класс, реализующий этот extension object, расположен в сборке Microsoft.SharePoint и помечен как internal. Как к нему доступиться? Разве что через Reflection..&lt;br /&gt;
&lt;br /&gt;
Но есть еще одна неприятность: существует досадный баг в Visual Studio 2010 (даже с примененным SP1), когда пытаешься заниматься отладкой XSLT в .Net Framework 3.5. Он описан на Microsoft Connect: &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/557335/xslt-debugger-doesnt-work-with-in-memory-transformation"&gt;XSLT debugger doesn't work with in memory transformation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Итог&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
В свете вышеописанного, я лично использую Visual Studio в простейшем варианте, практически как текстовый редактор... Хорошо еще, что сложных преобразований почти не бывает: 90% XSLT-кода копируется из стандартных файлов, собственного кода - очень немного. Необходимости в отладке пока практически не возникало.&lt;br /&gt;
&lt;br /&gt;
Комментарии по этой заметке приветствуются. Я буду очень рад, если я не прав - сам разработчик, хорошие intellisense и debug очень ценю.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-4608676882111219405?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/W5cnXXMCKbc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/4608676882111219405/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/xslt-visual-studio-intellisense.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/4608676882111219405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/4608676882111219405?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/W5cnXXMCKbc/xslt-visual-studio-intellisense.html" title="Про XSLT и Visual Studio: отладка и intellisense" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-iElEcHb2diE/TpsFQGXyrfI/AAAAAAAABAA/PrUMgxZaJC0/s72-c/vserrors.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/xslt-visual-studio-intellisense.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQFQ3czeyp7ImA9WhRSEU0.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-7937274274293604796</id><published>2011-10-17T09:10:00.000+04:00</published><updated>2011-11-12T18:31:52.983+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T18:31:52.983+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>SharePoint и XSLT: Объединяем две колонки в одну</title><content type="html">Довольно часто возникает такая задача: объединить несколько колонок списка в одну при отображении. Обычно это требуется в следующих случаях:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Когда в списке ну очень много колонок, поэтому при отображении эти данные поневоле приходится группировать&lt;/li&gt;
&lt;li&gt;Когда несколько колонок логично было бы объединить в один блок&lt;/li&gt;
&lt;li&gt;Иногда в некоторых колонках картинки или длинные текстовые описания, поэтому поля получаются очень разными по высоте, и оттого выглядят некрасиво&lt;/li&gt;
&lt;li&gt;Когда часть данных в списке важна при отображении, но присутствует редко. Например, комментарий от руководителя:
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-WKLYXlat5gY/TpnYvQp5QsI/AAAAAAAAA-M/lCzssFjBJc8/s1600/tasksWithPMsComment.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="244" src="http://1.bp.blogspot.com/-WKLYXlat5gY/TpnYvQp5QsI/AAAAAAAAA-M/lCzssFjBJc8/s640/tasksWithPMsComment.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
В общем, объединение двух колонок в одну при отображении позволяет сэкономить место на экране, улучшить внешний вид, поправить usability, "вписаться" в брэндбук... Это требуется часто, поэтому важно знать, как это можно сделать.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;Как видно из скриншота вверху, в качестве примера я решил использовать стандартный список "Tasks", в который добавил одну колонку типа "&lt;label for="onetidTypeMultiText"&gt;Multiple lines of text", и назвал её "PM's comment". То есть тот самый 4й вариант: такие комментарии слишком редки, чтобы для них держать целую колонку (да и колонка будет большая, потому что комментарий может содержать значительный объем текста) - но при этом очень важно их показать, если они всё-таки есть.&lt;/label&gt;&lt;br /&gt;
&lt;br /&gt;
Поэтому неплохо было бы отобразить комментарий руководителя где-нибудь рядом с заголовком задачи, да еще и пометить каким-нибудь красным цветом фона. Можно пойти даже дальше, и сделать так, чтобы в списке отображалась только небольшая часть комментария, а весь он был бы доступен только при наведении мышки.&lt;br /&gt;
&lt;br /&gt;
Эта задача прямо-таки идеальна для XSLT! Любые другие решения потребуют необоснованно больших трудозатрат. Если кто-то знает, как это можно легко и надежно сделать без XSLT - прошу оставить свои идеи в комментариях.&lt;br /&gt;
&lt;br /&gt;
Итак, давайте подумаем, какие изменения нужно будет сделать для того, чтобы воплотить нашу идею в жизнь:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Скрыть столбец "PM's comment" из представления&lt;/li&gt;
&lt;li&gt;Отобразить содержимое поля "PM's comment" в той же ячейке, где находится название задачи.&lt;/li&gt;
&lt;/ol&gt;
Скрыть столбец - довольно частая задача, и она реализуется средствами XSLT очень просто. Как я рассказывал в &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html"&gt;предыдущей статье&lt;/a&gt; серии, для определения, какой шаблон придется изменять, лучше всего использовать SharePoint Designer.&lt;br /&gt;
&lt;br /&gt;
Открываем SPD, находим наш список, и открываем его представление "All tasks":&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-U8mOj9Uni1c/TpncCMZqLGI/AAAAAAAAA-g/UpuIZ7sXR10/s1600/allitems.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-U8mOj9Uni1c/TpncCMZqLGI/AAAAAAAAA-g/UpuIZ7sXR10/s1600/allitems.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Очевидно, что для скрытия колонки нам потребуется скрыть два шаблона: для отображения заголовка этой колонки, и для отображения ячейки данных этой колонки. Довольно логично, что заголовок и ячейка данных отображаются разными шаблонами, не так ли? :)&lt;br /&gt;
&lt;br /&gt;
Хорошо, давайте ткнем на заголовок нашей колонки, и затем в статусной строке выделим элемент &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;xsl:template&amp;gt;&lt;/span&gt;&lt;/span&gt;, первый слева от тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;&lt;/span&gt; (а точнее, он будет отображен как &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;th.ms-vh2&amp;gt;&lt;/span&gt;&lt;/span&gt;):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-bhIq84tbu1g/TpnenihNQyI/AAAAAAAAA-o/JqwuQ-9l_X8/s1600/headerTemplate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-bhIq84tbu1g/TpnenihNQyI/AAAAAAAAA-o/JqwuQ-9l_X8/s1600/headerTemplate.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Надеюсь понятно, почему нужно выделять не первый справа шаблон, а немножко пролистать влево: если скрыть только текст заголовка, сама заголовочная ячейка (тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;&lt;/span&gt;) и соответствующая ей колонка - всё равно останутся видимыми и не исчезнут из таблицы.&lt;br /&gt;
&lt;br /&gt;
Теперь скопируем атрибуты выбранного нами тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;xsl:template&amp;gt;&lt;/span&gt;&lt;/span&gt;, выбрав в контекстном меню этого элемента &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Edit Tag...&lt;/span&gt;&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
Временно сохраним этот код в любом текстовом редакторе. Отлично, а теперь то же самое нужно проделать с любой из ячеек данных нашей колонки - здесь нам потребуется шаблон, первый слева после тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Получившиеся два тэга &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;xsl:template&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; нужно закрыть, т.к. при копировании из &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Edit Tag&lt;/span&gt;&lt;/span&gt; они получаются незакрытыми. А контент в них вставлять не нужно, т.к. мы их скрываем, а не заменяем.&lt;br /&gt;
&lt;br /&gt;
Итак, можете проверить, вот что должно получиться в итоге:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:template&lt;/span&gt; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"FieldRef_header.PM_x0027_s_x0020_comment"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;ddwrt:dvt_mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"header"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;match&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"header"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;ddwrt:ghost&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;""&lt;/span&gt; &lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:template&lt;/span&gt; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"FieldRef_printTableCell_EcbAllowed.PM_x0027_s_x0020_comment"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;match&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"printTableCellEcbAllowed"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;ddwrt:dvt_mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"body"&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: red;"&gt;ddwrt:ghost&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;""&lt;/span&gt; &lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Обратите внимание: я удалил строку &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;"hide"&lt;/span&gt;&lt;/span&gt; из атрибута &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;ddwrt:ghost&lt;/span&gt;&lt;/span&gt;. Иначе, дизайнер стирал бы эти шаблоны при каждом переключении между вкладками &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Code&lt;/span&gt;&lt;/span&gt; и &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Designer&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Давайте удостоверимся, работает ли это?&lt;br /&gt;
&lt;br /&gt;
Переходим на вкладку &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Code&lt;/span&gt;&lt;/span&gt;, отыскиваем XsltListViewWebPart, добавляем тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;Xsl&amp;gt;&lt;/span&gt;&lt;/span&gt;, в него вставляем стандартный &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;xsl:stylesheet&lt;/span&gt;&lt;/span&gt;, подключаем через &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;xsl:include&lt;/span&gt;&lt;/span&gt; файл стандартных преобразований &lt;b&gt;main.xsl&lt;/b&gt;, и наконец, вставляем наш код. Напомню, откуда брать код для &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;xsl:stylesheet&lt;/span&gt;&lt;/span&gt; и другие базовые вещи - я объяснял и подробно показывал в предыдущей статье серии: &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html"&gt;SharePoint и XSLT: Hello world!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Теперь переключаемся обратно - и видим, что колонка действительно пропала!&lt;br /&gt;
&lt;br /&gt;
Особо отмечу, почему мы должны скрывать эту колонку именно через XSLT (ведь её можно скрыть и через GUI, перейдя в настройки отображения и сняв соответствующую галочку): дело в том, что если колонка не включена в представление, данные этой колонки не будут переданы и в XSLT, и мы просто не сможем получить значения этой колонки из нашего преобразования. А значения-то нам нужны: ведь мы всё-таки собираемся отобразить эту колонку, хоть и в другом месте.&lt;br /&gt;
&lt;br /&gt;
Следующий шаг - изменить отображение колонки с названием ячейки. Для этого воспользуемся трюком с Conditional formatting, который я уже объяснял. Вкратце: выделяем любую ячейку колонки Title, жмем на Ribbon'е &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Conditional formatting =&amp;gt; Format column&lt;/span&gt;&lt;/span&gt;, прописываем любое условие (например &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;ID='0'&lt;/span&gt;&lt;/span&gt;), выставляем любой стиль, потом переключаемся во вкладку &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Code&lt;/span&gt;&lt;/span&gt; и смотрим, что получилось...&lt;br /&gt;
&lt;br /&gt;
Ага! В тег Xsl добавился новый шаблон.&lt;br /&gt;
&lt;br /&gt;
Этот шаблон идентифицируется атрибутами &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;match="FieldRef[@Name='LinkTitle']" mode="printTableCellEcbAllowed"&lt;/span&gt;&lt;/span&gt;, т.е. отображает ячейку с InternalName равным &lt;b&gt;LinkTitle&lt;/b&gt;. Это служебное поле с типом Computed, оно получается из стандартного &lt;b&gt;Title&lt;/b&gt; путем добавления ссылки на модальный диалог формы отображения элемента списка.&lt;br /&gt;
&lt;br /&gt;
Шаблон в целом очень простой. Он почти ничего не делает: только выводит тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;/span&gt;, добавляет ему несколько атрибутов, и вызывает нижестоящий шаблон (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;mode="PrintFieldWithECB"&lt;/span&gt;&lt;/span&gt;). После вызова этого шаблона, мы можем добавить наш собственный код, который будет отображать наше поле &lt;b&gt;PM's comment&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Даже имея самое скудное представление об XSLT, можно догадаться, что отобразить еще одно поле можно еще одним вызовом &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;xsl:apply-templates&amp;gt;&lt;/span&gt;&lt;/span&gt;, ведь очевидно, что содержимое поля &lt;b&gt;LinkTitle&lt;/b&gt; отображается именно c помощью этого шаблона.&lt;br /&gt;
&lt;br /&gt;
Но как же указать, что нужно отобразить именно поле &lt;b&gt;PM's comment&lt;/b&gt;? Прежде всего, нужно получить уникальный идентификатор этого поля, чтобы на него ссылаться. Это очень просто: в листинге наверху вы могли заметить строку &lt;span style="color: blue;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;PM_x0027_s_x0020_comment&lt;/span&gt;&lt;/span&gt; - это собственно и есть InternalName нашего поля.&lt;br /&gt;
&lt;br /&gt;
Дальше, изучив имеющийся &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;apply-templates&lt;/span&gt;&lt;/span&gt;, можно догадаться, что атрибут &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;select="."&lt;/span&gt;&lt;/span&gt; указывает на текущий обрабатываемый элемент. А текущий обрабатываемый элемент, как известно, задается с помощью атрибута &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;match&lt;/span&gt;&lt;/span&gt; текущего шаблона. Т.е., сейчаc обрабатывается &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;FieldRef[@Name='LinkTitle']&lt;/span&gt;&lt;/span&gt;, а нам нужно обработать&amp;nbsp;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;FieldRef[@Name='PM_x0027_s_x0020_comment']&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Т.е. согласно правилам XPath, следует передать в &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;apply-templates&lt;/span&gt;&lt;/span&gt; &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;select="../FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt;&lt;/span&gt;. Давайте попробуем. Вот такой будет код у второго вызова &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;apply-templates&lt;/span&gt;&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"../FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt; &lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"PrintFieldWithECB"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:with-param&lt;/span&gt; &lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"thisNode"&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$thisNode"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Переключаемся во вкладку Design, видим:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-umJ-UVLZL4U/TpntMZYYv5I/AAAAAAAAA-0/QvtVhWI7S7o/s1600/transformok.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="262" src="http://1.bp.blogspot.com/-umJ-UVLZL4U/TpntMZYYv5I/AAAAAAAAA-0/QvtVhWI7S7o/s400/transformok.png" width="238" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Отлично! Почти то, что нужно! Осталось только сделать это всё немного более приятным глазу.&lt;br /&gt;
&lt;br /&gt;
Для этого, давайте заключим наш дополнительный вызов xsl:apply-templates в div, и добавим этому div'у стили. Но постойте! Если мы сделаем div c padding'ом, и пропишем ему еще и цвет фона - получится нехорошо, т.к. этот квадрат будет виден во всех записях, даже там, где поле &lt;b&gt;PM's comment&lt;/b&gt; пустое.&lt;br /&gt;
&lt;br /&gt;
Т.е. нам нужен условный вывод тэга. На самом деле это реализуется элементарно в XSLT - в нем есть специальный тег &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;xsl:if&amp;gt;&lt;/span&gt;&lt;/span&gt; для таких вещей. Как создавать условие - можно подсмотреть у &lt;b&gt;Conditional Formatting&lt;/b&gt;. Помните же, мы задавали условие &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;ID='0'&lt;/span&gt;&lt;/span&gt;? SharePoint Designer сгенерировал соответствующую строку для этого, её можно найти внутри тега &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;xsl:attribute&lt;/span&gt;&lt;/span&gt; сразу после тега &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;td&lt;/span&gt;&lt;/span&gt;. Очевидно, что если заменить в этом сгенерированном условии &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;ID&lt;/span&gt;&lt;/span&gt; на&amp;nbsp;
&lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;PM_x0027_s_x0020_comment&lt;/span&gt;&lt;/span&gt;, и заменить &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;='0'&lt;/span&gt;&lt;/span&gt; на &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;!=''&lt;/span&gt;&lt;/span&gt;, то получится задать проверку на наличие нашего поля.&lt;br /&gt;
&lt;br /&gt;
Вобщем, в итоге у меня получился вот такой код:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:if&lt;/span&gt; &lt;span style="color: red;"&gt;test&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$thisNode/@PM_x0027_s_x0020_comment != ''"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;div&lt;/span&gt; &lt;span style="color: red;"&gt;style&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"background-color:#FFEEEE; margin: 5px; padding: 4px 10px; font-size: 9px;"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"../FieldRef[@Name='PM_x0027_s_x0020_comment']"&lt;/span&gt; &lt;span style="color: red;"&gt;mode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"PrintFieldWithECB"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:with-param&lt;/span&gt; &lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"thisNode"&lt;/span&gt; &lt;span style="color: red;"&gt;select&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$thisNode"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:apply-templates&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;div&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;xsl:if&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Конечно, к div нужно подключать css-класс, inline-стили написаны исключительно в качестве примера, для простоты.&lt;br /&gt;
&lt;br /&gt;
Если теперь перейти к просмотру нашего списка в браузере, получим следующую картину:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-IQsTzOjvP7Q/Tpn1m8U0NeI/AAAAAAAAA-8/2oCMC_1NHPk/s1600/tasks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-IQsTzOjvP7Q/Tpn1m8U0NeI/AAAAAAAAA-8/2oCMC_1NHPk/s1600/tasks.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Отличный результат, то, что нужно! В качестве дальнейших усовершенствований, можно предложить скрывать этот комментарий, заменяя его красным флажком - а отображать собственно комментарий только при наведении курсора мышки. Но это уже, как вы понимаете, задача связанная исключительно с дизайном и javascript, а решение сегодняшнего боевого примера на этом считаю успешно законченным.&lt;br /&gt;
&lt;br /&gt;
Подводя итог, сегодня мы научились объединять две и более колонок в одну при отображении списка, и это - ценой всего 10 строк XSL-преобразования (остальные строки нам сгенерировал дизайнер).&lt;br /&gt;
&lt;br /&gt;
Для вашего удобства, я разместил в интернете уже готовый исходный код XSL-преобразования обсуждавшегося примера: можете &lt;a href="https://sites.google.com/site/omlinfiles/MergeTwoColumns.xslt?attredirects=0&amp;amp;d=1"&gt;скачать&lt;/a&gt; и использовать в собственных целях.&lt;br /&gt;
&lt;br /&gt;
В &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt_26.html"&gt;следующей статье&lt;/a&gt; серии рассмотрена вариация этой задачи и реализован способ по отображению колонки в виде дополнительной строки в таблице.&lt;br /&gt;
&lt;br /&gt;
P.S.&amp;nbsp;Если вам понравилась статья, не забудьте &lt;a href="http://feeds.feedburner.com/omlin"&gt;подписаться на мой блог&lt;/a&gt; :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-7937274274293604796?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/S65tlMN_1Ko" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/7937274274293604796/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-xslt.html#comment-form" title="Комментарии: 7" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/7937274274293604796?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/7937274274293604796?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/S65tlMN_1Ko/sharepoint-xslt.html" title="SharePoint и XSLT: Объединяем две колонки в одну" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-WKLYXlat5gY/TpnYvQp5QsI/AAAAAAAAA-M/lCzssFjBJc8/s72-c/tasksWithPMsComment.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-xslt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YCSHc6cSp7ImA9WhRTEEs.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-1020493696536549520</id><published>2011-10-13T12:13:00.000+04:00</published><updated>2011-10-31T17:52:49.919+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-31T17:52:49.919+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>SharePoint и XSLT: Hello world!</title><content type="html">Продолжаю серию статей про XSLT в SharePoint.&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье 
&lt;span style="font-size: small;"&gt;я рассказывал, &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-xslt.html"&gt;почему XSLT в SharePoint - это важно&lt;/a&gt;.&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
Сегодня - перейду по-тихоньку к практике, и вы узнаете: как написать простейшее XSL-преобразование, как подключить его к списку, как выбрать шаблон для изменения, где подсмотреть примеры XSLT-кода, как выглядит дерево шаблонов веб-части XsltListViewWebPart, и еще много разных нюансов :) Поехали?&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span style="font-size: large;"&gt;XSL-преобразования&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: small;"&gt;Каждый наверное представляет, хотя бы примерно, что такое XSLT. Если сказать кратко, XSLT - это шаблон преобразования одного XML в другой, и сам представляющий из себя тоже разновидность XML :) Чаще всего, некий входной XML с данными преобразовывается в HTML, который затем отображается в браузере. Также происходит и в SharePoint, когда дело доходит до отображения данных списков, результатов поиска и др.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: small;"&gt;XSLT - язык очень мощный и богатый. Что нам нужно знать сейчас, это то, что основу XSLT составляют т.н. "шаблоны" (templates, элемент xsl:template), каждый из которых позволяет преобразовывать в HTML конкретный кусок входного XML. Подобно функциям, шаблоны могут вызывать друг друга (в том числе рекурсивно), передавать параметры и т.д.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: small;"&gt;Вторая важная деталь касательно XSLT - это тот факт, что шаблоны можно переопределять (override), и можно подключать файлы с шаблонами друг в друга, подобно библиотекам. Таким образом, всегда можно использовать по большей части стандартное преобразование, а в собственном файле просто переопределить один-два шаблона, которые нас непосредственно интересуют. Таким образом объем финального кода чаще всего бывает небольшим.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: small;"&gt;Но давайте же посмотрим, как это всё выглядит...&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Hello world в SharePoint XSLT&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: small;"&gt;Итак, давайте создадим самое простое XSLT-преобразование. Это можно сделать без Visual Studio и даже без SharePoint Designer. Очень просто и быстро:&lt;/span&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;Запускаем блокнот :)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;Открываем в браузере &lt;/span&gt;&lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;http://&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;ваш портал&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;/_layouts/xsl/main.xsl&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;Копируем первый тэг (xsl:stylesheet) в блокнот. Там куча объявлений xmlns, которые впоследствии могут понадобиться, - и запоминать их нет никакой необходимости, т.к. всегда можно получить из стандартных файлов SharePoint.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;Создаем тэг корневого шаблона, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;xsl:template match="/"&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt; - этот шаблон будет всегда выполняться первым. В качестве содержимого шаблона записываем строку &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;Hello world!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;Закрываем тэги, проверяем, должно получиться примерно следующее (я немного обрезал xsl:stylesheet, чтобы получше читалось):&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:stylesheet&lt;/span&gt; &lt;span class="attributeName"&gt;version&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"1.0"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:xsl&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://www.w3.org/1999/XSL/Transform"&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:template&lt;/span&gt; &lt;span class="attributeName"&gt;match&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"/"&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;
        Hello RUSUG!
    &lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:template&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:stylesheet&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;Загружаем файл в любую библиотеку документов.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;Открываем страницу с представлением списка, переходим в режим редактирования страницы, открываем настройки веб-части, и прописываем ссылку на наш xsl-файл.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;Вуаля&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt; :)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
Таким образом, мы создали уникальнейшее преобразование, чего угодно - в надпись &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Hello world&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; :)&lt;br /&gt;
&lt;br /&gt;
Конечно, это не совсем то, что может пригодиться нам в реальной действительности. Вы наверняка заметили, что в шаблоне мы прописывали атрибут &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;match="/"&lt;/span&gt;&lt;/span&gt; - это означает, что переопределяется корневой, самый первый шаблон. А шаблонов, которые можно переопределить, на самом деле, великое множество. Естественным образом, возникает следующий вопрос:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Какой шаблон переопределять?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Чтобы ответить на этот вопрос, лучше использовать более мощный инструмент, SharePoint Designer (далее - SPD).&lt;br /&gt;
&lt;br /&gt;
Итак, запускаем SPD, переходим к любому имеющемуся списку, в котором есть хотя бы одна запись, открываем его представление по умолчанию (All items), и выделяем какую-нибудь ячейку списка. Например, так:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-Tta-kojvRsU/TpP6QpTQAnI/AAAAAAAAA8E/-NH1pmSBVuQ/s1600/spd1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="260" src="http://4.bp.blogspot.com/-Tta-kojvRsU/TpP6QpTQAnI/AAAAAAAAA8E/-NH1pmSBVuQ/s640/spd1.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
И уже здесь, сразу же, мы получаем очень интересную подсказку в строке состояния внизу:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-UJ0laZZRnWo/TpP75cN1a-I/AAAAAAAAA8M/y-Zawfg-uZ4/s1600/spd2status.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="26" src="http://1.bp.blogspot.com/-UJ0laZZRnWo/TpP75cN1a-I/AAAAAAAAA8M/y-Zawfg-uZ4/s640/spd2status.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Ого! XSLT-разметка!&lt;br /&gt;
&lt;br /&gt;
Как можно догадаться, в строке состояния отображается полный "путь" к выделенному элементу в XSLT-разметке. Используя маленькую стрелочку слева, можно промотать этот путь до шаблонов верхнего уровня (если нужно). Код тэга любого шаблона можно посмотреть, выбрав в контекстном меню соответствующего элемента пункт "Edit Tag...":&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-YZaqOBESZj8/TpP-JwZdUPI/AAAAAAAAA8U/oCNuQZ32kcY/s1600/spd3edittag.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-YZaqOBESZj8/TpP-JwZdUPI/AAAAAAAAA8U/oCNuQZ32kcY/s1600/spd3edittag.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Что интересно, "путь" к выделенному элементу генерируется индивидуально для каждого конкретного элемента (т.е. туда захардкожено название колонки). И он отображается в "Edit Tag...", т.е. мы можем сразу же получить код для шаблона, который нам нужен (этот шаблон будет вдобавок визуально подсвечен дизайнером):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-Aa2AJVNPmpA/TpP-4l54iQI/AAAAAAAAA8c/hWBZUAxJkHQ/s1600/spd4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-Aa2AJVNPmpA/TpP-4l54iQI/AAAAAAAAA8c/hWBZUAxJkHQ/s1600/spd4.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Это означает, что если мы в своем собственном xslt-коде добавим представленный выше тэг xsl:template, и в качестве его содержимого пропишем, к примеру, строку &lt;i&gt;Hello world&lt;/i&gt;, то вместо значений заголовочной ячейки мы получим нашу тестовую строку!&lt;br /&gt;
&lt;br /&gt;
Звучит отлично, давайте попробуем.&lt;br /&gt;
&lt;br /&gt;
Переключаемся в режим Code:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-tVJ5eHsHt0c/TpQjNQGf3gI/AAAAAAAAA8k/6ntdWdbIshM/s1600/spd5code.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-tVJ5eHsHt0c/TpQjNQGf3gI/AAAAAAAAA8k/6ntdWdbIshM/s1600/spd5code.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Находим наш XsltListViewWebPart:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-XLYmylv2QKM/TpQjguF9RtI/AAAAAAAAA8s/SORil64mSRQ/s1600/spd6xlv.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-XLYmylv2QKM/TpQjguF9RtI/AAAAAAAAA8s/SORil64mSRQ/s1600/spd6xlv.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Добавляем в разметку XsltListViewWebPart элемент Xsl:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-G6oh8gRGqlU/TpQj9ZbxuyI/AAAAAAAAA88/VALjri6glS0/s1600/spd7xsl.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-G6oh8gRGqlU/TpQj9ZbxuyI/AAAAAAAAA88/VALjri6glS0/s1600/spd7xsl.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Создаем внутри Xsl-тэга элемент xsl:stylesheet, и в нем прописываем ссылку на стандартный файл main.xsl:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-vLhijiYS2ps/TpRChaZxkcI/AAAAAAAAA9E/7o5mky1utYE/s1600/spd8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-vLhijiYS2ps/TpRChaZxkcI/AAAAAAAAA9E/7o5mky1utYE/s1600/spd8.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Код для xsl:stylesheet (все эти xmlns), как я уже упоминал выше, можно легко подсмотреть в файле main.xsl, или любом другом файле вот этого очень полезного каталога:&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\XSL\&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
Именно в этом каталоге располагаются файлы, на которые я впоследствии буду часто ссылаться: main.xsl, vwstyles.xsl, fldtypes.xsl и др.&lt;br /&gt;
&lt;br /&gt;
Последним шагом, добавляем шаблон xsl:template - просто копируем его из Quick Tag Editor, а в качестве содержимого шаблона используем строку &lt;i&gt;Hello world&lt;/i&gt;. У меня в конечном итоге получился следующий код:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:stylesheet&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:x&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://www.w3.org/2001/XMLSchema"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:d&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://schemas.microsoft.com/sharepoint/dsp"&lt;/span&gt; &lt;span class="attributeName"&gt;version&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"1.0"&lt;/span&gt; &lt;span class="attributeName"&gt;exclude-result-prefixes&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"xsl msxsl ddwrt"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:ddwrt&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://schemas.microsoft.com/WebParts/v2/DataView/runtime"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:asp&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://schemas.microsoft.com/ASPNET/20"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:__designer&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://schemas.microsoft.com/WebParts/v2/DataView/designer"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:xsl&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"http://www.w3.org/1999/XSL/Transform"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:msxsl&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"urn:schemas-microsoft-com:xslt"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:SharePoint&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"Microsoft.SharePoint.WebControls"&lt;/span&gt; &lt;span class="attributeName"&gt;xmlns:ddwrt2&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"urn:frontpage:internal"&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:include&lt;/span&gt; &lt;span class="attributeName"&gt;href&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"/_layouts/xsl/main.xsl"&lt;/span&gt; &lt;span class="tagDelimiter"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:template&lt;/span&gt; &lt;span class="attributeName"&gt;match&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"FieldRef[@Name='LinkTitle']"&lt;/span&gt; &lt;span class="attributeName"&gt;name&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"LinkTitleNoMenu.LinkTitle"&lt;/span&gt; &lt;span class="attributeName"&gt;mode&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"Computed_LinkTitle_body"&lt;/span&gt; &lt;span class="attributeName"&gt;ddwrt:tag&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"a"&lt;/span&gt; &lt;span class="attributeName"&gt;ddwrt:dvt_mode&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"body"&lt;/span&gt; &lt;span class="attributeName"&gt;ddwrt:ghost&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;""&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;
        Hello world!
    &lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:template&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:stylesheet&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;
Переключаемся обратно в дизайнер, смотрим:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-VFo-AhMjoyQ/TpRFK5aCVtI/AAAAAAAAA9M/qxOLKIMIH48/s1600/spd9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-VFo-AhMjoyQ/TpRFK5aCVtI/AAAAAAAAA9M/qxOLKIMIH48/s1600/spd9.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Ага, уже интересно! Но что, если я хочу не подменить, а добавить какой-нибудь элемент оформления, или немного исправить существующий? Откуда взять исходный код шаблона, чтобы не писать его с нуля, а только слегка подправить?&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Где взять стандартный XSLT-код?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Это можно сделать опять же с помощью SharePoint Designer, и снова через вполне интуитивный визуальный интерфейс.&lt;br /&gt;
&lt;br /&gt;
Трюк здесь в следующем: в SPD есть очень интересная возможность, которая называется &lt;b&gt;Conditional Formatting&lt;/b&gt;. С помощью этого механизма можно подсветить или как-то выделить нужную ячейку (столбец) или целую строку в зависимости от некоторых условий.&lt;br /&gt;
&lt;br /&gt;
И если копнуть чуть глубже, оказывается, что работает этот механизм как раз на основе XSLT. То есть мы получаем визуальный интерфейс для генерации XSL-преобразования, с возможностью последующего подсматривания сгенерированного кода на вкладке &lt;b&gt;Code&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
По-моему, это прекрасная возможность изучить, пусть и частично, SharePoint'овские XSLT-шаблоны и способы их изменения.&lt;br /&gt;
&lt;br /&gt;
Давайте попробуем!&lt;br /&gt;
&lt;br /&gt;
Xsl-тэг, использовавшийся в предыдущем абзаце, я удалил, и переключился на вкладку дизайнера. Поехали!&lt;br /&gt;
&lt;br /&gt;
Щелкаем по нашей ячейке, на риббоне отыскиваем &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;Conditional formatting&lt;/span&gt;&lt;/span&gt;, выбираем &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;Format Column&lt;/span&gt;&lt;/span&gt;, - появляется диалоговое окно условий.&lt;br /&gt;
&lt;br /&gt;
Условия эти нужны, чтобы применять форматирование не ко всем строкам, а только к подходящим под заданные условия. В принципе логично :) Но в данном случае, нам это неинтересно, поэтому мы можем задать совершенно любое условие, в том числе невыполнимое, например, "ID &amp;lt; 0":&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-2JfGSqwmqos/TpXDWpBREJI/AAAAAAAAA90/owPke-bl_vE/s1600/conditionalformatting3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="194" src="http://1.bp.blogspot.com/-2JfGSqwmqos/TpXDWpBREJI/AAAAAAAAA90/owPke-bl_vE/s320/conditionalformatting3.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Жмем &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;Set Style&lt;/span&gt;&lt;/span&gt;, &amp;nbsp;появляется еще одно диалоговое окно, в котором можно выбрать уже конкретный стиль форматирования. Например, изменить цвет фона (background-color), или размер шрифта (font-size)... Как не трудно догадаться, эти настройки в итоге мапятся в соответствующие css-атрибуты. Впрочем, это нам тоже не интересно, можно выбрать первый попавшийся стиль.&lt;br /&gt;
&lt;br /&gt;
В общем, в конце концов нажимаем &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;ОК&lt;/span&gt;&lt;/span&gt;, стили применяются, если условие у нас было невыполнимым - внешний вид списка никак не изменится, но зато, если перейти на вкладку &lt;b&gt;Code&lt;/b&gt;, мы увидим, что у нашей XsltListViewWebPart появился сгенерированный тэг Xsl, с кучей кода.&lt;br /&gt;
&lt;br /&gt;
Этот код будет включать нужный шаблон, плюс наше невыполнимое условие и применение стиля. Этот кусок кода, кстати сказать, можно найти и безболезненно удалить. Он выглядит примерно так:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:attribute&lt;/span&gt; &lt;span class="attributeName"&gt;name&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"style"&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="tagDelimiter"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tagName"&gt;xsl:if&lt;/span&gt; &lt;span class="attributeName"&gt;test&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"$thisNode/@ID &amp;amp;lt; '0'"&lt;/span&gt; &lt;span class="attributeName"&gt;ddwrt:cf_explicit&lt;/span&gt;&lt;span class="attributeDelimiter"&gt;=&lt;/span&gt;&lt;span class="attributeValue"&gt;"1"&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;background-color: #FFEAAD;&lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:if&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="tagDelimiter"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tagName"&gt;xsl:attribute&lt;/span&gt;&lt;span class="tagDelimiter"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
После удаления этого куска, перед нами - девственно чистый исходный шаблон, который вы можете изменять, как вам вздумается. Рекомендую поизучать и поизменять этот шаблон в SharePoint Designer, на тестовом списке, и может быть, сразу попробовать реализовать пару каких-нибудь своих идей...&lt;br /&gt;
&lt;br /&gt;
Но с помощью &lt;span style="font-family: inherit;"&gt;Conditional Formatting&lt;/span&gt;, можно вытащить только пару шаблонов. Вдоволь с ними наигравшись и поняв их возможности, у вас неизбежно возникнет очередной вопрос:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Где взять полное дерево шаблонов?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Дерево шаблонов веб-части XsltListViewWebPart довольно сложное, и полное его описание - отдельная задача. Но базовые сведения о структуре шаблонов для отображения представления списка вполне можно получить из вот этой статьи на MSDN: &lt;a href="http://msdn.microsoft.com/en-us/library/ff604024.aspx"&gt;Overview of XSLT List View Rendering System&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
В виде упрощенной схемы эту структуру (она на самом деле очень неполная) можно представить следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-RUFT6gSpZuE/TpXwdAxaBGI/AAAAAAAAA-E/HkvILWdLdv8/s1600/xlvtemplatetree.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-RUFT6gSpZuE/TpXwdAxaBGI/AAAAAAAAA-E/HkvILWdLdv8/s320/xlvtemplatetree.jpg" width="187" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Чаще всего требуются:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Корневой шаблон (&lt;b&gt;/&lt;/b&gt;) - для добавления ссылок на скрипты и css-файлы (использовать нужно аккуратно, проверяя, не был ли уже этот же файл подключен ранее).&lt;/li&gt;
&lt;li&gt;Шаблон &lt;b&gt;RenderView&lt;/b&gt; - здесь выводится тэг &lt;span style="background-color: #eeeeee;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;/span&gt; (т.е. здесь к нему можно добавлять стили) и производится перечисление отображаемых на текущей странице элементов списка. Также, отсюда вызываются шаблоны группировки и отображения промежуточных итогов. Этот шаблон - хорошая точка для старта самостоятельных исследований.&lt;/li&gt;
&lt;li&gt;Шаблон &lt;b&gt;Item&lt;/b&gt; - вывод &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt;, &amp;nbsp;перечисление всех полей.&lt;/li&gt;
&lt;li&gt;Шаблон &lt;b&gt;PrintTableCellEcbAllowed&lt;/b&gt; - вывод &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #eeeeee;"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Подробно про переопределение отображения содержимого полей с помощью шаблонов типа &lt;b&gt;Text_body&lt;/b&gt; можно почитать на MSDN: &lt;a href="http://msdn.microsoft.com/en-us/library/ff606773.aspx"&gt;How to: Customize the Rendering of a Field on a List View&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
Перечислены, повторюсь, не все шаблоны. Более подробно вы можете исследовать сами. Исходный код всех этих шаблонов можно обнаружить в каталоге&lt;br /&gt;
&lt;blockquote&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\XSL\&lt;/span&gt;
&amp;nbsp;&lt;/blockquote&gt;
, в файлах &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;b&gt;vwstyles.xsl&lt;/b&gt;&lt;/span&gt; и &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;b&gt;fldtypes.xsl&lt;/b&gt;&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Подводя итог&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Итак, сегодня я показал, как можно начать работать с XSLT в SharePoint, как сделать первые шаги, что читать дальше, и где можно раскопать еще больше сведений.&lt;br /&gt;
&lt;br /&gt;
В следующих нескольких статьях серии будем рассматривать конкретные, наглядные примеры решения реальных задач с помощью XSL-преобразований, и попутно изучать расширения SharePoint, которые предусмотрены для XSLT-веб частей.&lt;br /&gt;
&lt;br /&gt;
До новых встреч! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-1020493696536549520?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/4cgzbiGRbnc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/1020493696536549520/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html#comment-form" title="Комментарии: 8" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1020493696536549520?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1020493696536549520?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/4cgzbiGRbnc/sharepoint-xslt-hello-world.html" title="SharePoint и XSLT: Hello world!" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-Tta-kojvRsU/TpP6QpTQAnI/AAAAAAAAA8E/-NH1pmSBVuQ/s72-c/spd1.jpg" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIERnw4eSp7ImA9WhdbE0g.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-8009766744879770727</id><published>2011-10-11T21:15:00.000+04:00</published><updated>2011-10-11T21:18:27.231+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-11T21:18:27.231+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>SharePoint Designer</title><content type="html">Давно хотел написать :)&lt;br /&gt;
&lt;br /&gt;
За первый год работы с SharePoint, не использовал SharePoint Designer (далее SPD) &lt;b&gt;ни разу&lt;/b&gt;. Питая с еще времен Perl'а стойкое отвращение к FrontPage, всегда считал любые визуальные редакторы HTML чем-то вроде костылей для людей, которые пока еще не выучили HTML...&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-3A5YYq4atRc/TpNTymKc7sI/AAAAAAAAA7s/fOD_mtZ4MyM/s1600/spd.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="56" src="http://3.bp.blogspot.com/-3A5YYq4atRc/TpNTymKc7sI/AAAAAAAAA7s/fOD_mtZ4MyM/s320/spd.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
В общем, не помню с чего это началось, но пришлось мне всё-таки установить, в конце концов, это "лишнее" приложение на рабочий компьютер... Ну, а раз установил - то полазал, пощупал, посмотрел - что к чему. Оказалось: штука очень полезная (именно для разработчика), и от FrontPage там мало что осталось. А вот различных интересных вещей можно подсмотреть - множество. И вот уже полгода - без SPD, как без третьей руки :)&lt;br /&gt;
&lt;br /&gt;
Нет, код конечно можно писать и без него, но постепенно SPD встал в один ряд с рефлектором, MSDN и с "investigate 14 hive" в плане исследований. А исследования у меня занимают нередко большую часть всего времени разработки какого-либо решения - потому что оказывается, что очень многое в SharePoint можно сделать имеющимися средствами, быстро и эффективно, сохраняя глубокую интеграцию с другими частями системы. И даже несмотря на то, что на исследования тратится очень много времени - результат, я считаю, того стоит.&lt;br /&gt;
&lt;br /&gt;
Ну да, и демонстрировать какие-то вещи на докладах - тоже очень удобно именно через SharePoint Designer. И на SharePoint Conference Russia, и на последней RUSUG - использовал именно его для демонстраций.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-8009766744879770727?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/PNy4GwwzXTo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/8009766744879770727/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-designer.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8009766744879770727?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8009766744879770727?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/PNy4GwwzXTo/sharepoint-designer.html" title="SharePoint Designer" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-3A5YYq4atRc/TpNTymKc7sI/AAAAAAAAA7s/fOD_mtZ4MyM/s72-c/spd.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-designer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAMRHk8eyp7ImA9WhdbFU0.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-6682905733474586047</id><published>2011-10-07T09:27:00.000+04:00</published><updated>2011-10-13T14:13:05.773+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-13T14:13:05.773+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="WSS3" /><category scheme="http://www.blogger.com/atom/ns#" term="MOSS2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><category scheme="http://www.blogger.com/atom/ns#" term="XSLT" /><title>SharePoint и XSLT: Почему XSLT - это важно?</title><content type="html">Начинаю серию статей по XSLT в SharePoint.&lt;br /&gt;
&lt;br /&gt;
XSLT в SharePoint - чрезвычайно мощный инструмент, глубоко интегрированный в систему. Даже в предыдущей, 2007й версии, роль XSLT была довольно велика - преобразования использовались при отображении результатов поиска (&lt;i&gt;CoreResultsWebPart&lt;/i&gt;), а также для кастомизаций отображения представлений и форм списков (&lt;i&gt;DataViewWebPart&lt;/i&gt; и &lt;i&gt;DataFormWebPart&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
В 2010м SharePoint'е XSL-преобразования используются еще более интенсивно. Отображение представлений всех стандартных списков, кроме календарей, осуществляется теперь именно через XSLT (&lt;i&gt;XsltListViewWebPart&lt;/i&gt;). Формы внешних списков также отображаются через XSLT (&lt;i&gt;XlstListFormWebPart&lt;/i&gt;), так что тенденция видна невооруженным взглядом: поскольку данные в SharePoint представляются в виде списков, на которые завязано всё, то можно смело сказать:&lt;br /&gt;
&lt;blockquote&gt;
&lt;i&gt;&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;, sans-serif;"&gt;&lt;span style="font-size: large;"&gt;Практически всё отображение данных в SharePoint'e осуществляется с помощью XSLT&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;В свете этой аксиомы, становится понятно, что для дизайнеров SharePoint, знание XSLT незаменимо. Иначе они не смогут ни поменять отображение различных стандартных типов полей в списках, ни сделать редизайн самого списка, ни переделать рендеринг списка с таблиц на div'ы - а я знаю, сделать это им очень хочется :)&lt;br /&gt;
&lt;br /&gt;
Не менее важно знание XSLT и для других людей, работающих с SharePoint - программистов, IT Pro, администраторов. Именно через XSLT можно реализовать KPI-светофоры и эффект красного глаза, сгруппировать вместе несколько полей при отображении, переделать пейджинг на более приличный вариант, удалить или изменить ненравящуюся многим ссылку "Добавить новую запись", изменить поведение и внешний вид группировки, и т.д.&lt;br /&gt;
&lt;br /&gt;
К примеру, мне удалось реализовать такую интереснейшую штуку, как иерархическое представление списка:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-Jeeg-qJRfes/To5QrB8RasI/AAAAAAAAA7Q/Gie_kz2A480/s1600/treeview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="155" src="http://1.bp.blogspot.com/-Jeeg-qJRfes/To5QrB8RasI/AAAAAAAAA7Q/Gie_kz2A480/s640/treeview.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
На создание этого представления ушло всего лишь около 3 дней работы. При этом, решение вполне универсальное, т.е. если в вашем списке есть Lookup-колонка, указывающая на этот же список - значит, ему можно за 2 минуты добавить иерархическое представление.&lt;br /&gt;
&lt;br /&gt;
С учетом того, что измененный список по-прежнему поддерживает все стандартные возможности - добавление колонок, сортировку и фильтрацию, соединения с другими веб-частями и т.д. - представьте сами, сколько бы вы писали такое же отображение, используя самописную веб-часть?:)&lt;br /&gt;
&lt;br /&gt;
Представление списка можно изменять очень сильно. Например, мне удалось добиться вот такого результата при отображении стандартного списка "Контакты", в который я добавил несколько дополнительных колонок стандартных типов:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-wm114443f2Q/To5RAvWcZHI/AAAAAAAAA7U/-WV97iFbGDw/s1600/contactsView.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="http://1.bp.blogspot.com/-wm114443f2Q/To5RAvWcZHI/AAAAAAAAA7U/-WV97iFbGDw/s640/contactsView.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Особенности этого представления:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Часть полей являются как бы служебными, и отображаются уникально - это ФИО и аватар (стандартная колонка типа Hyperlink or picture). Эффект мокрого пола для аватара реализован с помощью библиотеки reflection.js.&lt;/li&gt;
&lt;li&gt;Присутствует индикатор дней рождения. Этот индикатор, кстати говоря, полностью работоспособен и не зависит от вычисляемых колонок (с которыми бывают проблемы, т.к. на самом деле они обновляются только при изменении записи или колонки). За какое количество дней предупреждать о дне рождения - может быть задано специальной настройкой, передаваемой в качестве параметра через расширение ParameterBindings. С помощью другой подобной настройки можно задать отображение юбилеев - при этом стиль индикатора изменится.&lt;/li&gt;
&lt;li&gt;Основная часть добавляемых полей отображается снизу от индикатора дня рождения (или от ФИО, если индикатор отсутствует). При этом, отображением разных типов полей занимается SharePoint. Т.е., например, если вы добавите в представление Lookup-колонку, она отобразиться в виде ссылки, и т.д.&lt;/li&gt;
&lt;li&gt;Справа от ФИО расположена дополнительная панель для контактных данных. Это обычные поля, имеющие тип Single line of text или Hyperlink or picture - и их особое отображение реализовано с помощью &lt;a href="http://omlin.blogspot.com/2011/06/spfield.html"&gt;метаданных SPField&lt;/a&gt;, которые в XSLT передаются опять же, с помощью ParameterBindings.&lt;/li&gt;
&lt;li&gt;Представление полностью локализовано.&lt;/li&gt;
&lt;li&gt;Представление поддерживает все стандартные возможности - группировку, сортировку, фильтрацию, соединение с другими веб-частями, выделение одного и нескольких элементов, контекстный Ribbon, и т.д.&lt;/li&gt;
&lt;li&gt;Объем кода XSLT - всего 350 строк. Причем большая часть кода - это стандартные шаблоны, скопированные из OOTB файлов.&lt;/li&gt;
&lt;/ol&gt;
Как видите, использование XSLT-подхода при изменении отображения данных предоставляет довольно широкие возможности, гибкость и глубокую интеграцию в SharePoint.&lt;br /&gt;
&lt;br /&gt;
В &lt;a href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-hello-world.html"&gt;следующей статье&lt;/a&gt; серии, вы узнаете о том, как начать работать c XSLT: где подсмотреть примеры кода, как заставить представление вашего списка использовать этот код, как выглядит дерево шаблонов веб-части XsltListViewWebPart, откуда брать начальную версию версию этих шаблонов, - а также множество нюансов и тонкостей.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-6682905733474586047?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/sybHVhI-1ec" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/6682905733474586047/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/sharepoint-xslt-xslt.html#comment-form" title="Комментарии: 1" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6682905733474586047?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6682905733474586047?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/sybHVhI-1ec/sharepoint-xslt-xslt.html" title="SharePoint и XSLT: Почему XSLT - это важно?" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Jeeg-qJRfes/To5QrB8RasI/AAAAAAAAA7Q/Gie_kz2A480/s72-c/treeview.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/sharepoint-xslt-xslt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcNSX8zfyp7ImA9WhdUFEQ.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-8297969403684921526</id><published>2011-10-01T22:01:00.002+04:00</published><updated>2011-10-01T22:01:38.187+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-01T22:01:38.187+04:00</app:edited><title>9 статей про SharePoint</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-UvY1Xczv1Ss/TodVJi44umI/AAAAAAAAA6s/neq0UBVfusM/s1600/postsInBlog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://4.bp.blogspot.com/-UvY1Xczv1Ss/TodVJi44umI/AAAAAAAAA6s/neq0UBVfusM/s320/postsInBlog.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Прошло уже больше года с момента основания блога, и давно пора подвести некоторые итоги. За год, я опубликовал чуть больше 50 постов, большинство из которых - про SharePoint, и среди последних лично я выделяю девять, тянущих на звание "статья".&lt;br /&gt;
&lt;br /&gt;
Я думаю, многие из моих читателей пропустили хотя бы 1-2 статьи из этого списка. Поэтому, милости прошу, чтиво на выходные:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/07/html5-sharepoint.html"&gt;Использование HTML5 в формах списков SharePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/03/sharepoint.html"&gt;Локализация SharePoint: кодогенерация ресурсных файлов&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/07/spuimodaldialog-sharepoint.html"&gt;SP.UI.ModalDialog и стандартные диалоги SharePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/07/sms-sharepoint.html"&gt;SMS и SharePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/06/sharepoint.html"&gt;SharePoint: что такое хорошо, и что такое плохо&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/09/caml-sharepoint.html"&gt;Чем плох CAML в SharePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/07/xml-sharepoint-javascript.html"&gt;Работа с XML из SharePoint javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2011/04/sharepoint-foundation-2010.html"&gt;Вопросы для собеседования по SharePoint Foundation 2010&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2010/10/sharepoint-2010-ribbon-ootb.html"&gt;Как удалять и заменять OOTB кнопки на Ribbon'е&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
Также, &amp;nbsp;если кто-то вдруг не в курсе, в конце августа сего года я создал &lt;a href="http://amarkeev.wordpress.com/"&gt;еще один блог&lt;/a&gt;, английский, и уже успел настрочить туда 6 постов, из которых два даже были опубликованы на сайте &lt;a href="http://nothingbutsharepoint.com/"&gt;NothingButSharePoint.com&lt;/a&gt;:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://amarkeev.wordpress.com/2011/09/13/localization-sharepoint-xslt/"&gt;3 ways to localize SharePoint XSLT files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://amarkeev.wordpress.com/2011/08/29/selected-items-caml-query-js/"&gt;Selected items query with Javascript&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Это связано с тем, что в данный момент активно изучаю английский язык, и желание совмещать приятное с полезным, думаю, логично :)&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-8297969403684921526?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/SqFF8oaIxAk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/8297969403684921526/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/10/9-sharepoint.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8297969403684921526?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/8297969403684921526?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/SqFF8oaIxAk/9-sharepoint.html" title="9 статей про SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-UvY1Xczv1Ss/TodVJi44umI/AAAAAAAAA6s/neq0UBVfusM/s72-c/postsInBlog.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/10/9-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4DRHc8fyp7ImA9WhdXGUw.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-3668523728388082005</id><published>2011-09-01T22:30:00.000+04:00</published><updated>2011-09-02T01:02:55.977+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-02T01:02:55.977+04:00</app:edited><title>Чем плох CAML в SharePoint?</title><content type="html">В последнее время, я всё чаще и чаще пишу обертки для CAML. Началось всё, кстати, с моего любимого &lt;a href="http://spribbon.codeplex.com/"&gt;SharePoint 2010 Fluent Ribbon API&lt;/a&gt;, благодаря которому я очень глубоко изучил Ribbon. Кстати, ведь забыл в блог написать, всего пару дней назад, зарелизил &lt;a href="http://spribbon.codeplex.com/releases/view/65744"&gt;версию 1.3&lt;/a&gt;! :)&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-NDHKIOfRCFQ/Tl_xCWYZYbI/AAAAAAAAA4g/9jZsgTIz7BU/s1600/SPRibbonScreenShot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-NDHKIOfRCFQ/Tl_xCWYZYbI/AAAAAAAAA4g/9jZsgTIz7BU/s400/SPRibbonScreenShot.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Создание кнопки на ленте с помощью Fluent Ribbon&lt;/td&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;Дак вот, после Fluent Ribbon, на работе закодил Fluent List API, для программного создания списков. Идея примерно такая же: создаем ListDefinition, в нем - FieldDefinition'ы, потом есть ListController, ему в метод Create передаем описание списка и объект SPWeb - вуаля, список создан. Плюс там еще куча вкусных фишек, можно и представления создавать, и на заданные WebPart-страницы сразу же их выкладывать, и локализация поддерживается... В общем, пользуюсь с огромным удовольствием!&lt;br /&gt;
&lt;br /&gt;
Потом была еще обертка для SharePoint Batch List API, для пакетной обработки списков. Делал для рабочих нужд, не очень универсально. Если доделаю - обязательно выложу в паблик.&lt;br /&gt;
&lt;br /&gt;
Наконец, в последние дни усиленно кодю новый проект, SharePoint EcmaScript CAML Builder, предназначенный для работы с CAML запросами к спискам на стороне клиента. По задумке - это аналог знаменитого Camlex, но по синтаксису отличается: на JavaScript всё-таки нет возможности анализировать лямбда-выражения. Да и самих лямбда выражений, впрочем, там тоже нет :-)&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-rLrOVLVcFuU/Tl_xnCGkRpI/AAAAAAAAA4k/iBC0F9DAsa0/s1600/camljs_intellisense2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-rLrOVLVcFuU/Tl_xnCGkRpI/AAAAAAAAA4k/iBC0F9DAsa0/s1600/camljs_intellisense2.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Создание CAML-запросов с помощью CamlJS&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
К слову, &lt;a href="http://camlex.codeplex.com/"&gt;Camlex&lt;/a&gt; в серверном коде я всегда стараюсь использовать. Читабельность повышается неимоверно, и вероятность ошибки ниже. Конечно, проект не идеален: хотелось бы больше compile-time validation, но хотя бы runtime сообщения об ошибках очень внятные - уже здорово :) В общем, рекомендую!&lt;br /&gt;
&lt;br /&gt;
Подводя итог, тенденция видна невооруженным взглядом. Весь CAML - нуждается в обертывании (а это, по сути дела, весь SharePoint'овский служебный XML). Но почему? Давайте разбираться.&lt;br /&gt;
&lt;br /&gt;
Чтобы понять, в чем проблема, нужно заглянуть внутрь SharePoint. Если вы когда-нибудь это делали, то должны знать: центральный объект всего SharePoint'а - это некий SPRequest. Именно через этот класс в конце концов проходит, ну как минимум, вся работа с данными. А если взглянуть в этот класс, то, о ужас, обнаруживается, что это не более чем wrapper Unmanaged кода!!&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-aC_bG0qOIko/Tl_ttzuPsPI/AAAAAAAAA4c/kOEQWG8DPQ4/s1600/sprequest.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-aC_bG0qOIko/Tl_ttzuPsPI/AAAAAAAAA4c/kOEQWG8DPQ4/s320/sprequest.png" width="287" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Связь с мифическим ядром :)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Да-да, оказывается, когда-то SharePoint был полностью Unmanaged проектом, и это ядро осталось с тех самых времен.&lt;br /&gt;
&lt;br /&gt;
Ага, теперь-то понятно, откуда берутся все эти печально известные ошибки вида "Cannot complete this action. Please try again" :)&lt;br /&gt;
&lt;br /&gt;
И если проследить путь CAML-кусков, которые мы переправляем SharePoint'у, то вы очень скоро обнаружите, что все эти XMLSchema в конечном счете передаются именно в SPRequest. Иными словами, вся обработка XML осуществляется в неуправляемом коде.&lt;br /&gt;
&lt;br /&gt;
И вот в том самом мифическом ядре SharePoint'а, складывается впечатление, что существует несколько самописных XML-парзеров или препарсеров, чрезвычайно нежных и чувствительных к передаваемому им XML. По крайней мере, я ни разу не видел &lt;strong&gt;таких&lt;/strong&gt; ошибок при использовании любого современного известного парсера...&lt;br /&gt;
&lt;br /&gt;
Вот вам несколько ошибок XML-парзинга для примера:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://omlin.blogspot.com/2010/10/microsoft-magic-links.html"&gt;Ошибка размером в один пробел при локализации URL-полей списка&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://avishnyakov.wordpress.com/2011/06/09/sharepoint-bug-content-type-definition-%d1%81%d0%be%d0%b2%d1%81%d0%b5%d0%bc-%d0%bd%d0%b5-%d0%b4%d1%80%d1%83%d0%b6%d0%b0%d1%82-%d1%81-%d0%ba%d0%be%d0%bc%d0%bc%d0%b5%d0%bd%d1%82%d0%b0%d1%80%d0%b8/"&gt;В элементе FieldRefs при описании ContentType не поддерживаются XML-комментарии&lt;/a&gt; (вообще нонсенс)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://vtimashkov.wordpress.com/2011/06/17/synchronization-issue-of-choice-field-inside-microsoft-word/"&gt;Перенос строки в элементе Choices при описании Field приводит к проблеме в DIP при открытии документа в Microsoft Word&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
То есть, получается, что базовые возможности XML не всегда поддерживаются. С другой стороны, говорят, парзер спокойно глотает некоторые не well-formed XML-строки (что еще больший нонсенс).&lt;br /&gt;
&lt;br /&gt;
Итак, получаем следующее: XML-парзер явно кривоват. Но весь SharePoint завязан на CAML, без него не обойтись. Что делать? Решение естественное: генерировать код, который уж точно работает, и в котором никто не сможет уже поставить комментарий &lt;span style="color: #274e13;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&amp;lt;!-- Здесь был Вася --&amp;gt;&lt;/span&gt;&lt;/span&gt;, и сломать &lt;strong&gt;всё&lt;/strong&gt; :) Генерация позволит избежать повторяющихся ошибок, к тому же уничтожит вероятность опечаток, улучшит документированность и структурированность кода, ну и всё такое в общем :)&lt;br /&gt;
&lt;br /&gt;
Мораль: используете сложный CAML-код - пишите программную обертку.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-3668523728388082005?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/lyT0hbtQ-4U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/3668523728388082005/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/09/caml-sharepoint.html#comment-form" title="Комментарии: 11" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3668523728388082005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3668523728388082005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/lyT0hbtQ-4U/caml-sharepoint.html" title="Чем плох CAML в SharePoint?" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-NDHKIOfRCFQ/Tl_xCWYZYbI/AAAAAAAAA4g/9jZsgTIz7BU/s72-c/SPRibbonScreenShot.png" height="72" width="72" /><thr:total>11</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/09/caml-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YGRHw6fCp7ImA9WhdXF0o.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-7765478290793295981</id><published>2011-08-31T11:18:00.000+04:00</published><updated>2011-08-31T11:18:45.214+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-31T11:18:45.214+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Client Object Model" /><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="Ribbon" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="EcmaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Видео доклада SharePoint Ribbon и Office 365</title><content type="html">Видеозапись моего доклада с SharePoint Conference Russia наконец-то опубликована (как, впрочем, и видеозаписи докладов всех других участников)!&lt;br /&gt;
&lt;br /&gt;
Те, кто еще не смотрел, могут &lt;a href="http://rusug.net/News/Lists/Posts/Post.aspx?ID=56"&gt;посмотреть&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-7765478290793295981?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/VYnRP-JRqSA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/7765478290793295981/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/08/sharepoint-ribbon-office-365.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/7765478290793295981?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/7765478290793295981?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/VYnRP-JRqSA/sharepoint-ribbon-office-365.html" title="Видео доклада SharePoint Ribbon и Office 365" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/08/sharepoint-ribbon-office-365.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMEQHk6cSp7ImA9WhdXFkU.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-6562147083117516848</id><published>2011-08-30T09:00:00.008+04:00</published><updated>2011-08-30T09:00:01.719+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-30T09:00:01.719+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SPField" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Метаданные для SPField на стороне клиента</title><content type="html">В недавнем посте я предлагал &lt;a href="http://omlin.blogspot.com/2011/06/spfield.html"&gt;способ для запоминания метаданных SPField&lt;/a&gt;. И вот сегодня еще раз убедился, что пошел правильным путем.&lt;br /&gt;
&lt;br /&gt;
Возникла задача, получить метаданные поля на стороне клиента, используя SharePoint Client Object Model. Конкретно, нужно было получить все поля, помеченные как содержащие E-mail - у пользователей для простановки этих отметок есть соответствующий интерфейс.&lt;br /&gt;
&lt;br /&gt;
В итоге, пришел вот к такой простейшей функции:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt; getFieldAttribute(field, metadataKey) {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: darkgreen;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: darkgreen;"&gt;/// This function gets metadata key&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: darkgreen;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; xml = field.get_schemaXml();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; domElement = CUI.NativeUtility.createXMLDocFromString(xml);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; attribute;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (domElement.firstChild.getAttributeNS != &lt;span style="color: blue;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; domElement.firstChild.getAttributeNS != undefined)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; attribute = domElement.firstChild.getAttributeNS(&lt;span style="color: maroon;"&gt;'my'&lt;/span&gt;, metadataKey);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; attribute = domElement.firstChild.getAttribute(&lt;span style="color: maroon;"&gt;'p1:'&lt;/span&gt; + metadataKey);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; attribute;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Как видите, всё довольно просто. Когда расширять и интегрировать созданное решение просто - это хороший признак того, что делаешь правильно.&lt;br /&gt;
&lt;br /&gt;
Использовать - примерно так:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="background: white; color: black; font-family: Consolas; font-size: 10pt; overflow: auto;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; ctx = &lt;span style="color: blue;"&gt;new&lt;/span&gt; SP.ClientContext.get_current();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; list = ctx.get_web().get_lists().getById(SP.ListOperation.Selection.getSelectedList());&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; fields = list.get_fields();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;ctx.load(fields);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: darkgreen;"&gt;// ... load items or whatever you need here&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;ctx.executeQueryAsync(onSuccess, onFailure);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt; onSuccess() {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; emailFields = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Array();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; fieldEnumerator = fields.getEnumerator();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;while&lt;/span&gt; (fieldEnumerator.moveNext()) {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; field = fieldEnumerator.get_current();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; attribute = getFieldAttribute(field,&lt;span style="color: maroon;"&gt;'MyFieldType'&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (attribute == &lt;span style="color: maroon;"&gt;'Email'&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; emailFields.push(field.get_internalName());&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-6562147083117516848?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/8uOXDkvuJWY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/6562147083117516848/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/08/spfield.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6562147083117516848?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/6562147083117516848?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/8uOXDkvuJWY/spfield.html" title="Метаданные для SPField на стороне клиента" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/08/spfield.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcDRno_eCp7ImA9WhdQF0Q.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-3844272350130798451</id><published>2011-08-10T12:33:00.001+04:00</published><updated>2011-08-20T03:21:17.440+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-20T03:21:17.440+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>SharePoint и XSLT: содержание книги</title><content type="html">Думаю о возможности написания книги про &lt;b&gt;XsltListViewWebPart&lt;/b&gt;. Материала уже набирается немало, ниже приведено примерное содержание того, что я уже могу написать.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;Введение&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Почему нужно использовать XSLT?&lt;/blockquote&gt;&lt;blockquote&gt;2. Когда использование XSLT вредит?&lt;/blockquote&gt;&lt;blockquote&gt;3. Где в SharePoint еще нет XSLT, но очень хотелось бы, чтобы был&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;SharePoint Designer&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Почему всегда нужно начинать с SharePoint Designer&lt;/blockquote&gt;&lt;blockquote&gt;2. Conditional formatting&lt;/blockquote&gt;&lt;blockquote&gt;3. Как на самом деле работает Conditional formatting&lt;/blockquote&gt;&lt;blockquote&gt;4. Добавление XsltListViewWebPart через SharePoint Designer&lt;/blockquote&gt;&lt;blockquote&gt;5. Прямая правка Xslt через SharePoint Designer&lt;/blockquote&gt;&lt;blockquote&gt;6. Создание и подключение Xslt-файлов через SharePoint Designer&lt;/blockquote&gt;&lt;blockquote&gt;7. Границы применимости SharePoint Designer&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Visual Studio&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Настройка XSLT Intellisense&lt;/blockquote&gt;&lt;blockquote&gt;2. Применение XSLT-решений с помощью Visual Studio&lt;/blockquote&gt;&lt;blockquote&gt;3. Такие одинаковые, и такие разные - свойства XslLink и Xsl&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;4. Развертывание XsltListViewWebPart через Xml&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;5. Программное развертывание веб-части XsltListViewWebPart&lt;/blockquote&gt;&lt;blockquote&gt;6. Программное изменение SPView&lt;/blockquote&gt;&lt;blockquote&gt;7. Заметки по брэндингу&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;SPViewStyle&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Что такое SPViewStyle&lt;/blockquote&gt;&lt;blockquote&gt;2. Стандартные SPViewStyle&lt;/blockquote&gt;&lt;blockquote&gt;3. Создание собственного SPViewStyle&lt;/blockquote&gt;&lt;blockquote&gt;4. Альтернативы SPViewStyle&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;XSLT-шаблоны&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Формат входных данных&lt;/blockquote&gt;&lt;blockquote&gt;2. Шаблоны списка&lt;/blockquote&gt;&lt;blockquote&gt;3. Шаблоны группировки. Особенности реализации группировки на ajax&lt;/blockquote&gt;&lt;blockquote&gt;4. Шаблоны пэйджинга&lt;/blockquote&gt;&lt;blockquote&gt;5. Шаблоны для режима inplace-редактирования&lt;/blockquote&gt;&lt;blockquote&gt;6. Шаблоны полей&lt;/blockquote&gt;&lt;blockquote&gt;7. Шаблоны для блога&lt;/blockquote&gt;&lt;blockquote&gt;8. Шаблоны для форума&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Вспомогательные шаблоны&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;(глава по каждому шаблону)&lt;/blockquote&gt;&lt;blockquote&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Тонкая настройка XSLT&lt;/b&gt;&lt;/blockquote&gt;&lt;blockquote&gt;1. Дополнительные параметры: ParameterBindings&lt;/blockquote&gt;&lt;blockquote&gt;2. Пример использования ParameterBindings&lt;/blockquote&gt;&lt;blockquote&gt;3. Локализация и стандартные параметры в XsltListViewWebPart&lt;/blockquote&gt;&lt;blockquote&gt;4. Настройка и отключение пейджинга&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;Большой пример&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;
Вообще, планируются довольно интересные inline-примеры, в частности целая линия примеров по аватарам: например, как добавить аватары на форум, и т.п.&lt;br /&gt;
&lt;br /&gt;
Пока немного сумбурно, но общий смысл, думаю, понятен.&lt;br /&gt;
&lt;br /&gt;
От читателей хочется услышать:&lt;br /&gt;
&amp;nbsp;- будет ли это востребовано?&lt;br /&gt;
&amp;nbsp;- какие еще интересные моменты можно добавить к этой книге?&lt;br /&gt;
&amp;nbsp;- советы/предложения по реализации&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-3844272350130798451?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/qW3evSFQhdw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/3844272350130798451/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/08/sharepoint-xslt.html#comment-form" title="Комментарии: 8" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3844272350130798451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3844272350130798451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/qW3evSFQhdw/sharepoint-xslt.html" title="SharePoint и XSLT: содержание книги" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/08/sharepoint-xslt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4AQ3gzfyp7ImA9WhdaGU0.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-3956662096770404584</id><published>2011-07-29T16:27:00.001+04:00</published><updated>2011-10-29T20:15:42.687+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-29T20:15:42.687+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="MOSS2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SMS" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>SMS и SharePoint</title><content type="html">Уже больше года назад, мы писали на работе очень интересное решение, которое впоследствии вошло в состав нашего &lt;a href="http://deskwork.ru/"&gt;портала DeskWork&lt;/a&gt; - по отсылке оповещений, в том числе SMS. И вот в который раз убеждаюсь, насколько важно изучать SharePoint и его внутренности, потому что ценой минимальных усилий, оказывается, можно было бы глубоко сынтегрировать ту систему SMS-рассылок с SharePoint, получив массу вкусных бонусов (а может быть, мы это еще сделаем в будущем).&lt;br /&gt;
&lt;br /&gt;
Я имею в виду встроенную в SharePoint возможность отсылать SMS и даже MMS по протоколу &lt;a href="http://msdn.microsoft.com/en-us/library/dd774103.aspx"&gt;Office Mobile Service Protocol&lt;/a&gt;. Протокол вполне продуманный: предусмотрена пакетная отправка сообщений и интерфейс для получения статусов доставки... В этом посте я расскажу, как можно этот самый OMS использовать в своих решениях, и какие бонусы можно получить.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Office Mobile Service в SharePoint&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Как вы знаете, в SharePoint есть такая распространенная кнопочка "Alert Me", которая позволяет настраивать оповещения об изменении элементов списков или файлов в библиотеках документов. Также, подписываться можно не на конкретные элементы, а на целые списки. Это делается централизованно, через User Settings =&amp;gt; My Alerts.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-IIDQ_F2i_NI/TjKP3jHKtDI/AAAAAAAAAu4/Pn764Huapm8/s1600/AlertsPage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-IIDQ_F2i_NI/TjKP3jHKtDI/AAAAAAAAAu4/Pn764Huapm8/s1600/AlertsPage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
После выбора, на какой список мы хотим подписаться, или на какой элемент списка - отображается большая форма настроек, среди которых есть интересный пункт Delivery Methods.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-l6XiHRRpXkk/TjKPfuwUuuI/AAAAAAAAAu0/Voolig61qdM/s1600/DeliveryMethod.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="147" src="http://1.bp.blogspot.com/-l6XiHRRpXkk/TjKPfuwUuuI/AAAAAAAAAu0/Voolig61qdM/s640/DeliveryMethod.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Ага, вот они, наши SMS! Но по умолчанию, они задисейблены. Чтобы настроить их, переходим на сайт Central Administration, выбираем System Settings =&amp;gt; Configure mobile account:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ZBdVqvVIBUU/TjKMkmIC48I/AAAAAAAAAus/CGmRk5bUJ8g/s1600/SMSSettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="65" src="http://4.bp.blogspot.com/-ZBdVqvVIBUU/TjKMkmIC48I/AAAAAAAAAus/CGmRk5bUJ8g/s640/SMSSettings.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Здесь нам предложат ввести адрес веб-сервиса и логин-пароль.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1-1EvIJsntg/TjKOcX5DvYI/AAAAAAAAAuw/SUzX_GQXQFQ/s1600/ConfigureMobileAccount.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-1-1EvIJsntg/TjKOcX5DvYI/AAAAAAAAAuw/SUzX_GQXQFQ/s1600/ConfigureMobileAccount.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Что вводить!? Во-первых, можно создать собственный такой веб-сервис, который бы принимал данные в формате OMS, и затем использовал любой другой сервис по отсылке SMS-ок. Также, свой сервис можно заставить рассылать и напрямую, через GSM Gate.&lt;br /&gt;
&lt;br /&gt;
Процедура создания собственного веб-сервиса подробно описана &lt;a href="http://msdn.microsoft.com/en-us/library/ff606754.aspx"&gt;на MSDN&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Но конечно же, писать целый веб-сервис совсем необязательно. Есть большое число SMS-провайдеров, которые уже прекрасно понимают OMS-протокол и готовы для использования. Список их представлен &lt;a href="http://messaging.office.microsoft.com/HostingProviders.aspx"&gt;на сайте Microsoft&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Office Mobile Service в Outlook&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OMS-вебсервис, если его всё-таки написать, можно использовать не только в SharePoint, но и в Microsoft Office Outlook.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-sZRf6wQ4x50/TjKj3sKP3OI/AAAAAAAAAu8/tOGD6RbdP40/s1600/outlookSMSSettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="273" src="http://2.bp.blogspot.com/-sZRf6wQ4x50/TjKj3sKP3OI/AAAAAAAAAu8/tOGD6RbdP40/s400/outlookSMSSettings.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Если настроить Outlook на OMS-сервис, мы получаем возможность отсылать текстовые сообщения (есть даже Preview, как это будет выглядеть на среднем мобильном телефоне); плюс есть возможность отсылать оповещения о событиях календаря на телефон. &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Объектная модель для отсылки SMS&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Также, в SharePoint есть возможность самостоятельно отсылать SMS-ки через объектную модель... Простой вариант кода будет выглядеть примерно так:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;&lt;span style="color: green;"&gt;// Берем аккаунт из настроек веб-приложения, и получаем инстанс OMS веб-сервиса&lt;/span&gt;
&lt;span style="color: #2b91af;"&gt;SPMobileMessagingAccount&lt;/span&gt; account = webApp.OutboundSmsServiceAccount;
&lt;span style="color: #2b91af;"&gt;SPMobileMessageWebService&lt;/span&gt; messagingWebService = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPMobileMessageWebService&lt;/span&gt;(account);

&lt;span style="color: green;"&gt;// Формируем сообщение&lt;/span&gt;
&lt;span style="color: #2b91af;"&gt;SPMobileMessageSmsBuilder&lt;/span&gt; smsBuilder = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SPMobileMessageSmsBuilder&lt;/span&gt;(account);

&lt;span style="color: green;"&gt;// Получатели&lt;/span&gt;
smsBuilder.AddRecipient(mobile_telephone_number);

&lt;span style="color: green;"&gt;// Разбиваем текст на фрагменты по 132 символа (размер одной SMS)&lt;/span&gt;
smsBuilder.StartTextMessage();
List&amp;lt;&lt;span style="color: #2b91af;"&gt;StringBuilder&lt;/span&gt;&amp;gt; messageParts = SplitLongMessage(message)
&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;StringBuilder&lt;/span&gt; chunk &lt;span style="color: blue;"&gt;in&lt;/span&gt; messageParts)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;smsBuilder.AddChunk(chunk.ToString());
}
smsBuilder.EndTextMessage();

&lt;span style="color: green;"&gt;// At this point, the smsBuilder.Message property holds the message as an SPMobileSmsMessage object.&lt;/span&gt;
String messageXml = smsBuilder.GetMessageXml();

&lt;span style="color: green;"&gt;// Отсылаем&lt;/span&gt;
&lt;span style="color: #2b91af;"&gt;SPMobileMessageDeliveryReport&lt;/span&gt; report = messagingWebService.SendMessage(messageXml);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
Всё довольно прозрачно, документация по классам доступна на MSDN.&lt;br /&gt;
&lt;br /&gt;
Код взят из статьи &lt;a href="http://msdn.microsoft.com/en-us/library/ee537514.aspx"&gt;Overview of Mobile Messaging Development&lt;/a&gt;, там же вы можете посмотреть подробности и некоторые более сложные случаи (в частности, пакетную отправку).&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Выводы&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Итак, если мы хотим создать собственное решение для отправки SMS, нам в любом случае придется реализовывать сервис для отправки, и некий интерфейс для обращения к этому сервису. Причем, в любом случае для взаимодействия между сервисом и интерфейсом будет использоваться какой-то протокол или промежуточное хранилище данных. Если вовремя это понять и использовать протокол OMSP, то получим следующие бонусы:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Клиенты смогут использовать ваш сервис не только в SharePoint, но и в Outlook.&lt;/li&gt;
&lt;li&gt;Клиенты смогут использовать ваш сервис для отсылки оповещений об изменениях в списках (My Alerts).&lt;/li&gt;
&lt;li&gt;Есть сторонние решения, которые также рассчитаны на использование OMS - вы имеете отличный шанс получить небольшую денежку за каждую отправленную их решениями смску!&lt;/li&gt;
&lt;li&gt;Клиент всегда может сменить провайдера, использовав вместо вашего сервиса - чужой, что многократно повышает географическую актуальность решения. К примеру, вы заключили договор с неким провайдером, который умеет отправлять SMS только по России. Но продукт продается и за рубежом...&lt;/li&gt;
&lt;/ol&gt;В общем, на мой взгляд, OMS - это первое, на что должен посмотреть разработчик, который хочет внедрить в свое решение возможность отправки SMS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-3956662096770404584?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/lBRqvOZglLU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/3956662096770404584/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/07/sms-sharepoint.html#comment-form" title="Комментарии: 7" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3956662096770404584?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/3956662096770404584?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/lBRqvOZglLU/sms-sharepoint.html" title="SMS и SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-IIDQ_F2i_NI/TjKP3jHKtDI/AAAAAAAAAu4/Pn764Huapm8/s72-c/AlertsPage.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/07/sms-sharepoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4MR3czeip7ImA9WhZaGUk.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-1398035885287905410</id><published>2011-07-06T12:29:00.000+04:00</published><updated>2011-07-06T12:29:46.982+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-06T12:29:46.982+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Client Object Model" /><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2007" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="EcmaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Работа с XML в SharePoint из Javascript</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-yhZ3pPaz7OI/ThQcclUt3sI/AAAAAAAAAT4/BdYXmL9yWt0/s1600/1309940681_xml.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="160" src="http://2.bp.blogspot.com/-yhZ3pPaz7OI/ThQcclUt3sI/AAAAAAAAAT4/BdYXmL9yWt0/s200/1309940681_xml.png" width="160" /&gt;&lt;/a&gt;&lt;/div&gt;SharePoint очень тесно связан с XML. Все эти схемы полей и списков, определения элементов Ribbon, SharePoint Batch API, запросы SPQuery/CamlQuery - и многое другое. И если на стороне сервера всё более-менее понятно, там есть XmlReader/XmlWriter, XmlSerializer, XDocument и т.д., то что делать на стороне клиента?&lt;br /&gt;
&lt;br /&gt;
Как обрабатывать XML, формировать или изменять его, и какие для этого есть функции в SharePoint EcmaScript&amp;nbsp; - всю эту информацию я постарался собрать в сегодняшней статье.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span style="font-size: large;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;XmlWriter&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Впрочем, XmlWriter в SharePoint всё-таки есть. Располагается он в пространстве имен SP (т.е. SP.XmlWriter), а физически - находится в SP.Core.js. Применение в целом аналогично серверной версии, но поддерживаются только следующие методы:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;create(stringBuilder)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeStartElement(tagName)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeElementString(tagName, value)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeEndElement()&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeAttributeString(localname, value)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeStartAttribute(localname)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeEndAttribute()&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeString(value)&lt;/span&gt;&lt;/li&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;/span&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;writeRaw(xml)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;Впрочем, всё основное тут есть, так что можно смело использовать: в случае формирования XML в цикле или по каким-то сложным правилам, код станет гораздо более читаемым, по сравнению с формированием XML в строках. Простейший пример использования:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas, &amp;quot;Courier New&amp;quot;,&amp;quot;Courier&amp;quot;,monospace; font-size: 13;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;camlQuery&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;SP.CamlQuery();
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;sb&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;Sys.StringBuilder();
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;writer&amp;nbsp;=&amp;nbsp;SP.XmlWriter.create(sb);
 
writer.writeStartElement(&lt;span style="color: maroon;"&gt;"Where"&lt;/span&gt;);

writer.writeStartElement(&lt;span style="color: maroon;"&gt;"Eq"&lt;/span&gt;);

writer.writeStartElement(&lt;span style="color: maroon;"&gt;"FieldRef"&lt;/span&gt;);
writer.writeAttributeString(&lt;span style="color: maroon;"&gt;"Name"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: maroon;"&gt;"StatusID"&lt;/span&gt;);
writer.writeEndElement();

writer.writeStartElement(&lt;span style="color: maroon;"&gt;"Value"&lt;/span&gt;);
writer.writeAttributeString(&lt;span style="color: maroon;"&gt;"Type"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: maroon;"&gt;"Integer"&lt;/span&gt;);
writer.writeString(&lt;span style="color: maroon;"&gt;"1"&lt;/span&gt;);
writer.writeEndElement();

writer.writeEndElement();

writer.writeEndElement();
 
writer.close();
 
camlQuery.set_viewXml(sb.toString());
 
&lt;span style="color: darkgreen;"&gt;//&amp;nbsp;Result:&amp;nbsp;&amp;lt;Where&amp;gt;&amp;lt;Eq&amp;gt;&amp;lt;FieldRef&amp;nbsp;Name='StatusID'&amp;nbsp;/&amp;gt;&amp;lt;Value&amp;nbsp;Type='Integer'&amp;gt;1&amp;lt;/Value&amp;gt;&amp;lt;/Eq&amp;gt;&amp;lt;/Where&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Еще, при формировании XML может пригодиться вот этот метод:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://msdn.microsoft.com/en-us/library/ee659472.aspx"&gt;SP.Utilities.HttpUtility.escapeXmlText&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
, как не трудно догадаться из названия, этот метод эскейпит строку так, чтобы её потом можно было использовать в name или value xml-элементов и атрибутов.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Конвертируем объекты в XML&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Конечно, XmlWriter это здорово, но даже на стороне сервера его редко кто использует, потому что есть гораздо более интересные варианты. Например, XmlSerializer.&lt;br /&gt;
&lt;br /&gt;
И если немного поискать, то действительно, в файле SP.Runtime.js можно обнаружить методы &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.dataconvert.writedictionarytoxml.aspx"&gt;SP.DataConvert.writeDictionaryToXml&lt;/a&gt;&amp;nbsp;и SP.DataConvert.writePropertiesToXml. И они действительно сериализуют js-объекты... Но, использовать их врядли получится. Дело в том, что эти методы всегда генерируют теги Property.&lt;br /&gt;
&lt;br /&gt;
Например, вот такой код:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas, &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace; font-size: 13;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;sb&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;Sys.StringBuilder();
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;writer&amp;nbsp;=&amp;nbsp;SP.XmlWriter.create(sb);
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;context&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;SP.SerializationContext();
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;{&amp;nbsp;hello:&amp;nbsp;&lt;span style="color: maroon;"&gt;"world"&lt;/span&gt;,&amp;nbsp;complexObject:&amp;nbsp;{&amp;nbsp;property1:&amp;nbsp;&lt;span style="color: maroon;"&gt;"value1"&lt;/span&gt;,&amp;nbsp;property2:&amp;nbsp;&lt;span style="color: maroon;"&gt;"value2"&lt;/span&gt;}&amp;nbsp;};
&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;fields&amp;nbsp;=&amp;nbsp;[&lt;span style="color: maroon;"&gt;"hello"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: maroon;"&gt;"complexObject"&lt;/span&gt;];
SP.DataConvert.writeDictionaryToXml(writer,&amp;nbsp;dict,&amp;nbsp;&lt;span style="color: maroon;"&gt;"root"&lt;/span&gt;,&amp;nbsp;fields,&amp;nbsp;context);
&lt;span style="color: darkgreen;"&gt;//&amp;nbsp;Значение&amp;nbsp;сгенерированного&amp;nbsp;XML&amp;nbsp;можно&amp;nbsp;теперь&amp;nbsp;получить&amp;nbsp;через&amp;nbsp;sb.toString()&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Сгенерирует строку с вот таким XML:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas, &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace; font-size: 13;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;root&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"hello"&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"String"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;world&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"complexObject"&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"Dictionary"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"property1"&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"String"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;value1&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"property2"&lt;/span&gt;&amp;nbsp;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"String"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;value2&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;Property&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: maroon;"&gt;root&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Как видите, практическая ценность обоих этих методов весьма невелика. Поэтому, на практике я стараюсь везде где можно использовать json, или преобразование json в XML (например, с помощью &lt;a href="http://michalkorecki.com/content/introducing-json-xml-jquery-plugin"&gt;соответствующего jQuery-плагина&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Парзим XML&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Вообще, лучше jQuery для того, чтобы распарзить XML, по моему скромному мнению - ничего нет :) Делается это очень просто:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas, &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace; font-size: 13;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;jQueryObjectFromXml&amp;nbsp;=&amp;nbsp;$(xmlString);
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
, и дальше уже делаем всё что угодно с полученным jQuery-объектом...&lt;br /&gt;
&lt;br /&gt;
Впрочем, по умолчанию jQuery в SharePoint отсутствует, поэтому иногда может пригодиться и метод из SharePoint, который превращает XML в DOM-объект. Этот метод называется &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;CUI.NativeUtility.createXMLDocFromString&lt;/span&gt; и расположен в файле CUI.js.&lt;br /&gt;
&lt;br /&gt;
Пользоваться довольно просто. Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas, &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: 13;"&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt;&amp;nbsp;domElement&amp;nbsp;=&amp;nbsp;CUI.NativeUtility.createXMLDocFromString(&lt;span style="color: maroon;"&gt;'&amp;lt;root&amp;gt;&amp;lt;child&amp;nbsp;name="hello&amp;nbsp;world"/&amp;gt;&amp;lt;child&amp;gt;test&amp;nbsp;value&amp;lt;/child&amp;gt;&amp;lt;/root&amp;gt;'&lt;/span&gt;);
 
domElement.firstChild.nodeName
&lt;span style="color: darkgreen;"&gt;//&amp;nbsp;"root"&lt;/span&gt;
 
domElement.firstChild.firstChild.attributes[0].value
&lt;span style="color: darkgreen;"&gt;//&amp;nbsp;"hello&amp;nbsp;world"&lt;/span&gt;
 
domElement.firstChild.lastChild.text
&lt;span style="color: darkgreen;"&gt;//&amp;nbsp;"test&amp;nbsp;value"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Итоги&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Традиционно, подводим итоги :) Работать с XML в SharePoint приходится довольно часто, в том числе и на стороне клиента, из JavaScript. И как всегда, в SharePoint обнаруживается довольно большое количество интересных объектов и методов, которые можно использовать в собственных целях. Документация по этим возможностям, к сожалению, чаще всего очень скудная - или отсутствует совсем. Поэтому, изучать приходится самостоятельно.&lt;br /&gt;
&lt;br /&gt;
Надеюсь, эта статья будет уважаемым читателям полезна в плане увеличения кругозора, а также подтолкнет к собственным исследованиям в разных других направлениях :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-1398035885287905410?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/ArSsuMVPGLQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/1398035885287905410/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/07/xml-sharepoint-javascript.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1398035885287905410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/1398035885287905410?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/ArSsuMVPGLQ/xml-sharepoint-javascript.html" title="Работа с XML в SharePoint из Javascript" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-yhZ3pPaz7OI/ThQcclUt3sI/AAAAAAAAAT4/BdYXmL9yWt0/s72-c/1309940681_xml.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/07/xml-sharepoint-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcNQH8zcSp7ImA9WhdTEEw.&quot;"><id>tag:blogger.com,1999:blog-70467739252625072.post-970150473444200942</id><published>2011-07-05T10:00:00.003+04:00</published><updated>2011-07-07T09:54:51.189+04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-07T09:54:51.189+04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SPS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SPF2010" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint" /><category scheme="http://www.blogger.com/atom/ns#" term="HTML5" /><category scheme="http://www.blogger.com/atom/ns#" term="SPList" /><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint2010" /><title>Использование HTML5 в формах списков SharePoint</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-v8IFAAhJVqs/TgOdOkn7yYI/AAAAAAAAATc/s8UXezYxUPE/s1600/HTML5_Logo_256.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-v8IFAAhJVqs/TgOdOkn7yYI/AAAAAAAAATc/s8UXezYxUPE/s200/HTML5_Logo_256.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Недавно я писал &lt;a href="http://omlin.blogspot.com/2011/06/list-form-sharepoint.html"&gt;про RenderingTemplate и использование перегруженного ListFieldIterator&lt;/a&gt; для того, чтобы изменять отображение форм списков SharePoint. В качестве примера использования этого способа, я привел скриншот проекта, где поля списка распределены по вкладкам. Также, в том посте был выложен для скачивания "базовый" проект-пример на эту тему.&lt;br /&gt;
&lt;br /&gt;
Сегодня я хочу еще раз вернуться к RenderingTemplate и ListFieldIterator, рассмотрев их более тщательно и иллюстрированно, на другом примере - внедряя элементы управления HTML5 в формы списков SharePoint.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div style="clear: both;"&gt;&lt;/div&gt;&lt;span style="font-size: large;"&gt;Что это дает?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Как вы наверняка знаете, HTML5 добавляет множество крайне интересных типов элементов управления, в числе которых:&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="clear: right; float: right; margin-bottom: 1em; text-align: right;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-3dl2aHbHA0k/TgnfssYPK2I/AAAAAAAAATg/2LCqUMlwim4/s1600/expiresFromOpera.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-3dl2aHbHA0k/TgnfssYPK2I/AAAAAAAAATg/2LCqUMlwim4/s1600/expiresFromOpera.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Модифицированное html5-поле&lt;br /&gt;
Expires из стандартного списка&lt;br /&gt;
"Announcements", &lt;br /&gt;
вид из браузера Opera&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;ul&gt;&lt;li&gt;элемент управления для выбора даты/времени&lt;/li&gt;
&lt;li&gt;элемент управления для ввода телефонного номера&lt;/li&gt;
&lt;li&gt;элемент управления для ввода адреса электронной почты&lt;/li&gt;
&lt;li&gt;элемент управления для ввода URL&lt;/li&gt;
&lt;/ul&gt;Есть и другие, полный список можно найти &lt;a href="http://www.w3schools.com/html5/att_input_type.asp"&gt;на W3Schools&lt;/a&gt;. Помимо типа элементов, добавились также и атрибуты, например, мне очень нравится встроенная валидация с помощью атрибутов &lt;a href="http://www.w3schools.com/html5/att_input_required.asp"&gt;required&lt;/a&gt; и &lt;a href="http://www.w3schools.com/html5/att_input_pattern.asp"&gt;pattern&lt;/a&gt;. Очень интересны также списки-подсказки (атрибут &lt;a href="http://www.w3schools.com/html5/att_input_list.asp"&gt;list&lt;/a&gt;) и текст-подсказка (атрибут &lt;a href="http://www.w3schools.com/html5/att_input_placeholder.asp"&gt;placeholder&lt;/a&gt;). Т.о., использование HTML5 позволяет серьезно сэкономить на размере страницы, улучшить её производительность за счет отказа от javascript-решений, использовать оформление и локализацию браузера.&lt;br /&gt;
&lt;br /&gt;
К сожалению, список браузеров, поддерживающих HTML5-элементы управления, &lt;a href="http://www.coreservlets.com/html5-tutorial/input-types.html"&gt;очень невелик&lt;/a&gt;. Лучшая реализация сегодня - у Opera, на втором месте Chrome, все другие браузеры очень ощутимо отстают. Причем, в Опере SharePoint вообще ведет себя неважно - некоторые скрипты не работают, иногда неверно отображается дизайн, и т.д.&lt;br /&gt;
&lt;br /&gt;
Поэтому, вынужден признать, что основная практическая ценность данной статьи - в объяснении приемов подмены полей, а не в добавлении HTML5 на формы :( Возможно, через некоторое время всё изменится, когда во все современные браузеры добавят поддержку форм HTML5. Я на это очень надеюсь (ибо возможности действительно классные)!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Rendering Template&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Давайте же уже приступим к делу! Первым делом, создаем проект SharePoint Empty Project, и добавляем в него SharePoint Mapped Folder &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;CONTROLTEMPLATES&lt;/span&gt;&lt;/span&gt;. Внутри этой папки, создаем User Control, и называем его &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: #cccccc;"&gt;Html5ListForm.ascx&lt;/span&gt;&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-EXUDqNDgO1I/TgORX-D57cI/AAAAAAAAATU/VM4NTJcQRIY/s1600/RenderingTemplateControl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="206" src="http://2.bp.blogspot.com/-EXUDqNDgO1I/TgORX-D57cI/AAAAAAAAATU/VM4NTJcQRIY/s320/RenderingTemplateControl.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Копируем туда код из стандартного шаблона отображения &lt;b&gt;ListForm&lt;/b&gt;, который вы можете найти в файле &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;14\TEMPLATE\CONTROLTEMPLATES\DefaultTemplates.ascx&lt;/span&gt;&lt;/span&gt;. Не забываем также скопировать и весь требуемый заголовочный код (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue;"&gt;@&lt;/span&gt; &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;&lt;span style="color: #990000;"&gt;..&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt; &lt;span style="background-color: yellow;"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;).&lt;br /&gt;
&lt;br /&gt;
Далее, ищем контрол ListFieldIterator и заменяем его на его же наследника:&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre&gt;&lt;span style="background-color: yellow;"&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;%&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;@&lt;/span&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: red;"&gt;Register&lt;/span&gt; &lt;span style="color: red;"&gt;Tagprefix&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"my"&lt;/span&gt; &lt;span style="color: red;"&gt;Namespace&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"Html5ListForms"&lt;/span&gt; &lt;span style="color: red;"&gt;Assembly&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"$SharePoint.Project.AssemblyFullName$"&lt;/span&gt; &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;%&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;
&lt;span style="color: green;"&gt;&amp;lt;!-- skipped for clarity... --&amp;gt;&lt;/span&gt;

&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SharePoint:RenderingTemplate&lt;/span&gt; &lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"Html5ListForm"&lt;/span&gt; &lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"server"&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: green;"&gt;&amp;lt;!-- skipped for clarity... --&amp;gt;&lt;/span&gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;my:Html5FieldIterator&lt;/span&gt; &lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"ListFieldIterator1"&lt;/span&gt; &lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"server"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: green;"&gt;&amp;lt;!-- skipped for clarity... --&amp;gt;&lt;/span&gt;
&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515;"&gt;SharePoint:RenderingTemplate&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;FormsModernizr&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Вслепую подключать HTML5 нехорошо и неправильно. Для определения, поддерживает ли браузер те или иные функции HTML5, существует специальная js-библиотека, которая даже была включена в состав ASP.Net MVC. Называется эта библиотека - &lt;a href="http://www.modernizr.com/docs/"&gt;Modernizr&lt;/a&gt;, но работает она на стороне клиента. А хотелось бы использовать ее на стороне сервера, ведь иначе никакой экономии в размере страницы не получится...&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Bgz8Ast8V5k/TgOdHL79HEI/AAAAAAAAATY/hewcoGF6ZuY/s1600/modernizr_logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-Bgz8Ast8V5k/TgOdHL79HEI/AAAAAAAAATY/hewcoGF6ZuY/s1600/modernizr_logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
И вот недавно я как раз наткнулся на реализацию &lt;a href="http://tripleodeon.com/2010/10/modernizr-on-the-server-side/"&gt;server-side modernizr на PHP&lt;/a&gt;. Идея довольно простая: при первой загрузке, все сведения из modernizr сохраняются в cookies, потом страница сразу же перезагружается, а после этого клиентский modernizr уже не нужен, и можно спокойно осуществлять любые проверки на стороне сервера, выпарзивая нужные сведения из cookies.&lt;br /&gt;
&lt;br /&gt;
Недолго думая, написал крохотный контрол, который реализует эту идею.&lt;br /&gt;
&lt;br /&gt;
Этот контрол, как не трудно догадаться, тоже следует добавить в RenderingTemplate, куда-нибудь повыше:&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;my:FormsModernizr &lt;/span&gt;&lt;/span&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"FormsModernizr1" &lt;/span&gt;&lt;/span&gt;&lt;span style="color: black; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: blue;"&gt;"server"&lt;/span&gt;&lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Я назвал этот контрол FormsModernizr, поскольку он позволяет определять только поддержку новых типов элементов управления и их атрибутов для html-форм. Другие возможности Modernizr'а не используются.&lt;br /&gt;
&lt;br /&gt;
В этом контроле я перегрузил метод OnLoad, в котором проверяю, есть ли уже cookies с данными из клиентского Modernizr'а. Если кукисы еще не поставлены, то с помощью Page.Response.Write рендерим простейшую html-страницу, содержащую:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Скрипт Modernizr, который определяет, какие фишки HTML5 доступны&lt;/li&gt;
&lt;li&gt;Функцию stringify, для преобразования объекта Modernizr в json-массив&lt;/li&gt;
&lt;li&gt;Код для простановки cookies&lt;/li&gt;
&lt;li&gt;Код для перезагрузки страницы&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;Далее, вызываем Page.Response.End - страница отсылается клиенту, Modernizr определяет возможности браузера, эти сведения сериализуются и попадают в кукисы. После этого страница перегружается.&lt;br /&gt;
&lt;br /&gt;
Случай disabled cookies также корректно обрабатывается ;).&lt;br /&gt;
&lt;br /&gt;
Если cookies наконец-то получены, то json-строка десериализуется (с помощью &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx"&gt;DataContractJsonSerializer&lt;/a&gt;) в статический объект FormsModernizr.Data. Ок, теперь можно использовать этот объект в классе, ответственном за отображение полей.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Html5FieldIterator&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Следующий шаг - это создание класса &lt;b&gt;Html5FieldIterator&lt;/b&gt;, который собственно и будет отображать поля. Идея состоит в перегрузке метода Render, и использовании коллекции SPContext.Current.FormContext.FieldControlCollection для стандартного отображения полей.&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы пометить некоторые нестандартные типы полей, которые нельзя определить по FieldType (например, поле для хранения номера телефона: у него FieldType = Text, а html5 type='tel'), мы будем использовать метаданные. &lt;a href="http://omlin.blogspot.com/2011/06/spfield.html"&gt;Про метаданные для SPField&lt;/a&gt; я рассказывал в предыдущем посте.&lt;br /&gt;
&lt;br /&gt;
Обычно, я еще дополнительно делаю ApplicationPage для настройки метаданных полей, и подключаю ссылку на неё на страницу настроек списка (List Settings). Но в этом примере, метаданные для полей можно просто расставить вручную, что я и сделал в FeatureReceiver.&lt;br /&gt;
&lt;br /&gt;
Тип поля определили, но вот как теперь срендерить наши замены для полей?&lt;br /&gt;
&lt;br /&gt;
Сделать это на самом деле довольно просто, можно воспользоваться даже несколькими разными способами. Например, довольно перспективно выглядит вариант с использованием &lt;a href="http://htmlagilitypack.codeplex.com/"&gt;Html Agility Pack&lt;/a&gt;, когда все контролы рендерятся стандартными средствами, после чего результат загружается в объект HtmlDocument, выбираются нужные элементы типа input, и им выставляется нужный тип...&lt;br /&gt;
&lt;br /&gt;
Можно пойти более примитивным, но одновременно - более надежным путем, не полагаясь на html-парзинг, и полностью срендерив нужные input'ы. При этом, чтобы форма не сломалась, этим input'ам следует проставить правильные атрибуты id и name, которые бы корректно понимались SharePoint'ом. Брать эти атрибуты следует как раз из той самой коллекции правильных контролов,&amp;nbsp;SPContext.Current.FormContext.FieldControlCollection, на серверной стороне они называются UniqueId и ClientId.&lt;br /&gt;
&lt;br /&gt;
Код метода, заменяющего поле, у меня получился вот каким:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="overflow: auto;"&gt;&lt;pre style="background: white; color: black; font-family: Consolas; font-size: 13;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt;&amp;nbsp;RenderHtml5Field(&lt;span style="color: #2b91af;"&gt;HtmlTextWriter&lt;/span&gt;&amp;nbsp;output,&amp;nbsp;&lt;span style="color: #2b91af;"&gt;BaseFieldControl&lt;/span&gt;&amp;nbsp;fieldControl,&amp;nbsp;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;nbsp;fieldType)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&amp;nbsp;(fieldControl.Field.Required&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;FormsModernizr&lt;/span&gt;.Data.Input.Required)
&amp;nbsp; &amp;nbsp; {
        output.AddAttribute(&lt;span style="color: #a31515;"&gt;"required"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #a31515;"&gt;"required"&lt;/span&gt;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.AddAttribute(&lt;span style="color: #a31515;"&gt;"type"&lt;/span&gt;,&amp;nbsp;fieldType);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.AddAttribute(&lt;span style="color: #a31515;"&gt;"id"&lt;/span&gt;,&amp;nbsp;fieldControl.ClientID);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.AddAttribute(&lt;span style="color: #a31515;"&gt;"name"&lt;/span&gt;,&amp;nbsp;fieldControl.UniqueID);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.RenderBeginTag(&lt;span style="color: #2b91af;"&gt;HtmlTextWriterTag&lt;/span&gt;.Input);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output.RenderEndTag();
}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Перед вызовом этого метода, fieldType определяется через метаданные поля, и проверяется, поддерживается ли такой тип поля браузером - через FormsModernizr.Data. Если тип не поддерживается, рендерится стандартный контрол. Более подробно можно посмотреть в &lt;a href="https://sites.google.com/site/omlinfiles/HTML5ListForms.zip?attredirects=0&amp;amp;d=1"&gt;проекте-примере&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Итоги&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Итак, сегодня мы детально изучили процесс подмены контролов на формах списков SharePoint, познакомились с тем, как можно использовать Modernizr на стороне сервера, и может быть, немного подизучили HTML5 :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Замечание&lt;/b&gt;: Решение &lt;b&gt;не&lt;/b&gt; будет работать в Office365 и вообще в песочнице, поскольку ascx-файл с нашим RenderingTemplate'ом должен попасть в папку &lt;span style="background-color: #cccccc;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, &amp;quot;Courier&amp;quot;, monospace;"&gt;CONTROLTEMPLATES&lt;/span&gt;&lt;/span&gt;, а эта возможность для Sandboxed Solutions заблокирована.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/70467739252625072-970150473444200942?l=omlin.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/omlin/~4/sxJYY9tP_7Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://omlin.blogspot.com/feeds/970150473444200942/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://omlin.blogspot.com/2011/07/html5-sharepoint.html#comment-form" title="Комментарии: 4" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/970150473444200942?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/70467739252625072/posts/default/970150473444200942?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/omlin/~3/sxJYY9tP_7Q/html5-sharepoint.html" title="Использование HTML5 в формах списков SharePoint" /><author><name>Andrey Markeev</name><uri>https://profiles.google.com/114112803853944210209</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-HqbbyIJ3d4k/AAAAAAAAAAI/AAAAAAAAA0M/sdOs0fWPuP4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-v8IFAAhJVqs/TgOdOkn7yYI/AAAAAAAAATc/s8UXezYxUPE/s72-c/HTML5_Logo_256.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://omlin.blogspot.com/2011/07/html5-sharepoint.html</feedburner:origLink></entry></feed>

