<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
	<channel>
		<title>Jonkas SharePoint Blog</title>
		<link>http://www.jonka.de/blog/index.php</link>
		<description><![CDATA[No Footer]]></description>
		<copyright>Copyright 2012, jonka</copyright>
		<managingEditor>jonka</managingEditor>
		<language>de-DE</language>
		<generator>SPHPBLOG 0.4.8</generator>
		<item>
			<title>ASP.NET Session verschwunden</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry101202-154018</link>
			<description><![CDATA[Manchmal verstehe ich Microsoft Software wirklich nicht...<br /><br />Ich hatte einen ganz einfachen Fall:<br />Eine ASP.NET-Formular sollte einige Informationen in der Session vorhalten. Nach dem Submit sollte wieder auf die Informationen des ersten Aufrufs zugegriffen werden:<br /><br />Seite.aspx.cs:<br />---------------<br /><code>protected void Page_Load(object sender, EventArgs e)<br />{<br />if (Session[&quot;Foo&quot;] != &quot;Bar&quot;)<br />{<br />	//... Tue irgendwas nur einmal<br />	Session[&quot;Foo&quot;] = &quot;Bar&quot;;<br />}<br />}</code><br /><br />Seltsamerweise war jedes Mal nach dem Submit die Sessionvariable leer, obwohl diese definitiv gesetzt wurde! Der Internet Explorer 8 akzeptierte auch cookies, und auch sonst war alles richtig. Das Phänomen trat unter Visual Studio 2010 auch auf anderen Rechnern auf.<br /><br />Aber: Mit Firefox funktionierte es!<br /><br />Warum wurde die Session unter Internet Explorer 8 gelöscht, unter Firefox blieb sie aber erhalten?<br /><br />Aus Spaß suchte ich im gesamten Projekt nach &quot;Session.Clear&quot; und &quot;Session.Abandon&quot; und fand auch eine entsprechende Zeile. In der &quot;Default.aspx.cs&quot;.<br /><br />Default.aspx.cs:<br />-------------------<br /><code>protected void Page_Load (object sender, EventArgs e)<br />{<br />Session.Abandon();<br />}</code><br /><br />Ich setzte einen Breakpoint in der &quot;Default.aspx.cs&quot;, rief &quot;Seite.aspx&quot; auf und siehe da, der Debugger blieb nach dem Laden der Webseite in der Code-Behind der &quot;Default.aspx&quot; stehen! WTF?<br />Wurde &quot;Seite.aspx&quot; mit Firefox geladen, wurde &quot;Default.aspx.cs&quot; nicht angesprungen!<br /><br />Die Lösung für die verschwundene Session war damit zwar behoben, aber es bleibt noch das Rätsel, warum der IE8 zumindest unter Visual Studio 2010 die Default-Seite lädt, obwohl sie gar nicht aufgerufen werden soll.<br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry101202-154018</guid>
			<author>jonka</author>
			<pubDate>Thu, 02 Dec 2010 14:40:18 GMT</pubDate>
		</item>
		<item>
			<title>SharePoint 2010 und IE6</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry100520-165408</link>
			<description><![CDATA[Microsoft hat es zwar schon lang und breit angekündigt, aber man muss es doch gesehen haben, um es zu glauben: Der Internet Explorer 6 wird mit SharePoint 2010 nicht mehr unterstützt! HTML und JavaScript sind jetzt einfach nicht mehr kompatibel.<br />Das ist zwar sehr lobenswert, aber einige Firmen werden dennoch Schwierigkeiten mit dieser Tatsache haben. Insbesondere große Konzerne haben oft weltweit noch IE6 im Einsatz.<br />Unten sind zwei Screenshots einer Standard SharePoint Site zu sehen: <br /><br />Site mit IE7 geöffnet:<br /><br /><a href="javascript:openpopup('images/SP2010withIE7.jpg',1056,634,false);"><img src="images/SP2010withIE7.jpg" width="484" height="291" border="0" alt="" /></a><br /> <br /><br />Site mit IE6 geöffnet:<br /><br /><a href="javascript:openpopup('images/SP2010withIE6.jpg',1044,643,false);"><img src="images/SP2010withIE6.jpg" width="484" height="298" border="0" alt="" /></a><br /> <br /><br /><br />Wie man ganz gut sehen kann, gibt es offenbar keine Chance, dass die Seite doch noch irgendwie mit IE6 benutzbar ist.<br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry100520-165408</guid>
			<author>jonka</author>
			<pubDate>Thu, 20 May 2010 14:54:08 GMT</pubDate>
		</item>
		<item>
			<title>SharePoint 2010 + Silverlight 3 Client OM -  Cross Domain Calls</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry100304-165016</link>
			<description><![CDATA[Ok, das Thema ist zwar schon alt, aber im Zusammenhang mit dem neuen SharePoint Client OM wieder aktuell: Silverlight Cross Domain Calls.<br />Silverlight Applets, die auf dem SharePoint Server liegen und per Microsoft.SharePoint.Client auf z.B. Listen zugreifen, funktionieren eigentlich auf Anhieb. Man greift hier auf den aktuellen Kontext zu (sprich, die aktuelle URL):<br /><br /><code>context = SP.ClientContext.Current;<br /></code><br />Wenn man aber eine Silverlight Anwendung nicht als Sandboxed Solution direkt in SharePoint lädt, wird man beim ersten Versuch zu debuggen einen &quot;Security.Error&quot; bekommen, denn man muss jetzt die URL zum Server explizit angeben:<br /><br /><code>context = new SP.ClientContext(&quot;http://devserver001/sites/Jonka/&quot;);<br /></code><br /><code>Exception	{System.Security.SecurityException ... etc<br /></code><br />Silverlight versucht hier wieder auf die Datei &quot;clientaccesspolicy.xml&quot; zuzugreifen, um die Berechtigungen zu prüfen - man befindet sich schließlich gerade auf der Domain &quot;localhost&quot;.<br /><br />Also wird clientaccesspolicy.xml mit folgendem Inhalt ganz einfach im root der entsprechenden SharePoint Application abgelegt (z.B. C:\inetpub\wwwroot\wss\VirtualDirectories\80)<br /><br /><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;<br />&lt;access-policy&gt;<br />  &lt;cross-domain-access&gt;<br />    &lt;policy&gt;<br />      &lt;allow-from http-request-headers=&quot;*&quot;&gt;<br />        &lt;domain uri=&quot;http://localhost:53659&quot;&gt;&lt;/domain&gt;<br />      &lt;/allow-from&gt;<br />      &lt;grant-to&gt;<br />        &lt;resource path=&quot;/&quot; include-subpaths=&quot;true&quot;&gt;&lt;/resource&gt;<br />      &lt;/grant-to&gt;<br />    &lt;/policy&gt;<br />  &lt;/cross-domain-access&gt;<br />&lt;/access-policy&gt;<br /></code><br /><br />Man kann auch &lt;domain uri=&quot;*&quot;&gt; eintragen, dann gibt es keine Beschränkung der URL.<br /><br />Die Datei ist natürlich nicht aufrufbar, da SharePoint das Dateisystem nicht nach außen öffnet. Zum Glück gibt es in SharePoint 2010 immer noch die beliebten &quot;Managed Paths&quot;, um solche Inhalte zu veröffentlichen.<br /><br />In der Central Administration unter &quot;Application Management&quot; - &quot;Manage web applications&quot; im Ribbon kann die Einstellung geöffnet werden:<br /><br /><a href="javascript:openpopup('images/2010-03-04_161443.png',558,381,false);"><img src="images/2010-03-04_161443.png" width="484" height="330" border="0" alt="" /></a><br /><br />Hier eine &quot;Explicit inclusion&quot; anlegen, und /clientaccesspolicy.xml als Pfad angeben:<br /><br /><a href="javascript:openpopup('images/2010-03-04_161529.png',473,219,false);"><img src="images/2010-03-04_161529.png" width="473" height="219" border="0" alt="" /></a><br /><br />Ein Klick auf &quot;Add Path&quot;, und alles sollte funktionieren:<br /><br /><a href="javascript:openpopup('images/2010-03-04_161550.png',488,171,false);"><img src="images/2010-03-04_161550.png" width="484" height="170" border="0" alt="" /></a><br /><br />Dann kann auch von der Visual Studio Debug-Umgebung aus auf SharePoint 2010 Listen zugegriffen werden:<br /><br /><a href="javascript:openpopup('images/2010-03-04_160919.png',724,616,false);"><img src="images/2010-03-04_160919.png" width="484" height="412" border="0" alt="" /></a><br /><br /><br />Quellen:<br /><a href="http://www.silverlighthack.com/post/2008/11/08/Silverlight-clientaccesspolicyxml-files-for-the-Enterprise-%28Part-1-of-2%29.aspx" target="_blank" >http://www.silverlighthack.com/post/200 ... -2%29.aspx</a><br /><a href="http://timheuer.com/blog/archive/2008/04/06/silverlight-cross-domain-policy-file-snippet-intellisense.aspx" target="_blank" >http://timheuer.com/blog/archive/2008/0 ... sense.aspx</a><br /><br /><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry100304-165016</guid>
			<author>jonka</author>
			<pubDate>Thu, 04 Mar 2010 15:50:16 GMT</pubDate>
		</item>
		<item>
			<title>Silverlight WebPart in SharePoint aktualisieren</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry100302-173405</link>
			<description><![CDATA[Silverlight und SharePoint zu verbinden macht seit Version 2010 und dem Client Object Model (komisch, dass das nicht COM abgekürzt wird... *hust*) auf einmal richtig Sinn. Es gibt auch viele Arten, aus VisualStudio 2010 heraus eine Silverlight Applikation zu deployen. Ich hatte mich zunächst für ein PostBuild Deployment in das SharePoint ClientBin entschieden, mit dem Standard Silverlight-WebPart für die Anzeige.<br /><br />Leider cached der Internet-Explorer das XAP-File immer, so dass Änderungen nicht Sichtbar werden, und manuell den Cache zu leeren, ist viel zu umständlich. Zum Glück kann man den Cache auch per Commando-Zeile löschen, auch wenn der Befehl sich einem nicht sofort erschließt: (Gilt natürlich nur für den Internet Explorer)<br /><br /><code>RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8<br /></code><br /><br />Im Post-Build event steht also folgendes:<br /><br /><a href="javascript:openpopup('images/2010-03-01_182057.jpg',503,210,false);"><img src="images/2010-03-01_182057.jpg" width="484" height="202" border="0" alt="" /></a><br /><br /><code>copy SilverlightSharePointDemo.* &quot;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin&quot;<br />RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8<br /></code><br /><br />Danach kann man mit F6 das Projekt kompilieren und mit F5 im Browser neu laden. Alle Änderungen sollten dann sofort sichtbar sein.<br /><br /><br /><b>Quelle:</b><br /><a href="http://blogs.techrepublic.com.com/window-on-windows/?p=574" target="_blank" >http://blogs.techrepublic.com.com/windo ... ows/?p=574</a><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry100302-173405</guid>
			<author>jonka</author>
			<pubDate>Tue, 02 Mar 2010 16:34:05 GMT</pubDate>
		</item>
		<item>
			<title>Visual Studio + SharePoint 2010 - Debugging funktioniert nicht</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry100301-175954</link>
			<description><![CDATA[So, endlich mein erster Blogeintrag zu SharePoint 2010:<br /><br />Für den Anfang wollte ich mit Visual Studio 2010 RC auf SharePoint 2010 Beta2 ein Visual WebPart deployen. Also habe ich VS 2010 RC Premium auf dem bestehenden SharePoint Server installiert. Leider musste ich feststellen, dass die Premium Version von Visual Studio nicht die SharePoint Vorlagen enthielt, obwohl sie eigentlich enthalten sein müssten. Aber für den Release Candidate braucht man offenbar in jedem Falle die Ultimate Variante:<br /><br />Ich empfehle dafür den Link auf das ISO File, der sich auf der Download-Seite ganz klein versteckt:<br /><br /><a href="http://download.microsoft.com/download/7/5/8/7580D7D8-7F31-4358-9761-71033D91AB29/VS2010Ult_RC.iso" target="_blank" >http://download.microsoft.com/download/ ... Ult_RC.iso</a><br /><br />Nachdem das installiert ist, kann man auch die SharePoint Vorlagen auswählen und eine Site des lokalen SharePoint zum Deployen und Debuggen angeben:<br /><br /><a href="javascript:openpopup('images/2010-03-01_160343.jpg',600,474,false);"><img src="images/2010-03-01_160343.jpg" width="484" height="382" border="0" alt="" /></a><br /><br />Leider bekam ich immer sofort oder beim Starten mit F5 einen der folgenden Fehler angezeigt:<br /><br /><a href="javascript:openpopup('images/2010-03-01_160700.jpg',415,165,false);"><img src="images/2010-03-01_160700.jpg" width="415" height="165" border="0" alt="" /></a><br /><br /><code>&quot;Could not load the Web.config configuration file. Check the file for any malformed XML elements, and try again. The following error occurred: The local SharePoint server is not  available. Check that the server is running and connected to the SharePoint farm.&quot;<br /></code><br /><br />oder:<br /><br /><a href="javascript:openpopup('images/Message1.jpg',417,295,false);"><img src="images/Message1.jpg" width="417" height="295" border="0" alt="" /></a><br /><br /><code>&quot;Cannot connect to the SharePoint site: ... Make sure that the site URL is valid, that the SharePoint site is running on the local computer, and that the current user has the necessary permissions to access the site. [...]&quot;<br /></code><br /><br />Unten in der Error List gibt es auch noch eine Meldung:<br /><br /><a href="javascript:openpopup('images/2010-03-01_161310.jpg',536,103,false);"><img src="images/2010-03-01_161310.jpg" width="484" height="93" border="0" alt="" /></a><br /><br /><code>&quot;Error occurred in deployment step &#039;Recycle IIS Application Pool&#039;: The local SharePoint server is not available. Check that the server is running and connected to the SharePoint farm.&quot;<br /></code><br />Das ist natürlich nicht sehr aussagekräftig, denn natürlich läuft der lokale SharePoint und lässt sich auch lokal aufrufen. Also habe ich in einer WinForms-Anwendung versucht über das normale Objektmodell (SPSite) auf den Server zuzugreifen und siehe da, der Benutzer hat keine Datenbank-Berechtigungen!<br /><br />In der neuen Kombination von Windows Server 2008 R2 und SQL Server 2008 R2 hat eben nicht mehr jeder lokale Admin auch gleichzeitig volle Datenbank-Berechtigungen - auch dann nicht, wenn alles auf einem System installiert ist. Auch hilft es offenbar nicht, den Benutzer als SharePoint Farm-Administrator einzutragen.<br />Das ist insofern komisch, da man hingegen Zugriff auf die SharePoint-Admin und -Search Datenbanken erhält. (Bug oder Feature?)<br /><br />Gibt man seinem Benutzer, mit dem man am System angemeldet ist, Zugriff auf die entsprechende Content-DB (z.B. SharePoint_Content_1234567890) und die Config-DB (z.B. SharePoint_Config_1234567890) kann man auch wieder auf das Objektmodell zugreifen und das Debugging klappt.<br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry100301-175954</guid>
			<author>jonka</author>
			<pubDate>Mon, 01 Mar 2010 16:59:54 GMT</pubDate>
		</item>
		<item>
			<title>SQL Server - Auto-ID Wert nach INSERT ermitteln</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry091111-172246</link>
			<description><![CDATA[Heute hatte ich mal wieder das alte Problem, dass beim SQL Update eines gerade angelegten Datensatzes dieser nicht aktualisiert wurde, weil die automatisch vergebene ID der Auto-Increment Spalte sich nicht im bestehenden Objekt wiederfand.<br />Normalerweise muss ich mich ja damit nicht rumärgern, weil ich entweder einen OR-Maper verwende, der das alles regelt, oder GUIDS verwende, die ich ja schon vorher kenne. Aber hier war es mal simples ADO.NET und Auto-IDs. Also wieder recherchieren...<br />Und damit ich das nicht nochmal raussuchen muss - falls ich es vergessen sollte - hier das einfachste Vorgehen in C# für ein INSERT mit darauffolgendem UPDATE mit ADO.NET auf einem SQL Server:<br /><br />Um die eben erzeugte ID beim INSERT zu erhalten genügt es, ein SELECT scope_identity() an das INSERT Statement zu hängen.<br />z.B.:<br /><code><br />INSERT INTO Customer (Name, LastName)<br />VALUES (&#039;Max&#039;, &#039;Mustermann&#039;)<br />SELECT scope_identity()<br /><br /></code><br /><br />Dann natürlich nicht mehr ExecuteNonQuery() ausführen, sondern ExecuteScalar():<br /><br /><code><br />object ret = command.ExecuteScalar();<br />int id = Convert.ToInt32(ret);<br />customer.Id = id;<br /><br /></code><br /><br />Dann bekommt man die eben erzeugte ID in einem Command wieder zurück, und dann klappts auch mit dem Update.<br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry091111-172246</guid>
			<author>jonka</author>
			<pubDate>Wed, 11 Nov 2009 16:22:46 GMT</pubDate>
		</item>
		<item>
			<title>SharePoint 2007 - Eigenen Custom Field Type erstellen</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry090922-150018</link>
			<description><![CDATA[Einen eigenen Custom Field Type zu erstellen ist eigentlich gar nicht so schwer, wenn man den richtigen Weg wählt. Das Thema ist zwar schon alt, und im Internet gibt es bereits einige Einträge zu diesem Thema, aber ich möchte hier einmal einen konkreten Anwendungsfall zeigen, bei dem solche eigenen Field Types wirklich Sinn machen.<br /><br />Ein solcher Custom Field Type kann nach dem Einbinden in jeder Liste oder Dokumentenbibliothek als zusätzlicher Spaltentyp eingebunden werden:<br /><br /><a href="javascript:openpopup('images/2009-09-22_144645.png',271,336,false);"><img src="images/2009-09-22_144645.png" width="271" height="336" border="0" alt="" /></a><br /><br />Der erste Versuch, das vielversprechende <a href="http://www.codeplex.com/wspbuilder" target="_blank" >WSPBuilder</a> Visual Studio Template zu verwenden, schlug leider fehl, weil die Daten meiner ListBox sich nicht speichern ließen... Der Manuelle Weg, auf Basis des Microsoft Beispielcodes, funktioniert allerdings auch zufriedenstellend. Auf den Komfort eines deploybaren WSP-Files muss man dann zunächst zwar verzichten, aber zum Entwickeln geht es dafür wesentlich schneller.<br /><br />Im Folgenden wird gezeigt, wie man eine eigene Listen-Spalte definiert, die im Edit-Mode über eine Multi-Select-Box gefüllt wird, in der Ansicht aber für jede Auswahl ein entsprechendes Bild anzeigt. Die Piktogramme werden aus einer fest definierten SharePoint Image-Library geladen:<br /><br /><a href="javascript:openpopup('images/2009-09-22_144709.png',724,195,false);"><img src="images/2009-09-22_144709.png" width="484" height="130" border="0" alt="" /></a><br /><br /><ins>Und so wird&#039;s gemacht:</ins><br /><br /><b>1. Leeres Visual Studio Projekt anlegen.</b><br /><br /><b>2. Der Einfachheit halber eine Ordnerstruktur anlegen</b><br /><br /><pre><br />TEMPLATE<br />TEMPLATE\CONTROLTEMPLATES<br />TEMPLATE\XML<br /><br /></pre><br /><br />Und eine Referenz zu <em>Microsoft.SharePoint</em> hinzufügen, für die Verwendung der Basisklassen.<br /><br /><a href="javascript:openpopup('images/2009-09-22_144726.png',240,316,false);"><img src="images/2009-09-22_144726.png" width="240" height="316" border="0" alt="" /></a><br /><br /><b>3. Die Assembly signieren</b><br /><br />Der Public Key Token wird später für die XML-Felddefinition benötigt.<br /><br /><b>4. Die Felddefinion anlegen</b><br /><br />Für die eigene Felddefinion wird eine Klasse benötigt, die von einem der SharePoint Feld-Basistypen ableitet. Im Folgenden wird von SPFieldMultiLine abgeleitet, um große Textmengen in diesem Feld speichern zu können. Das neue Feld hat den Namen Symbol - das Wort sollte also überall durch einen eigenen Namen ersetzt werden ;)<br /><br />SymbolField.cs Listing:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">
<span class="kwrd">using</span> Microsoft.SharePoint;
<span class="kwrd">using</span> Microsoft.SharePoint.WebControls;

<span class="kwrd">namespace</span> SymbolFieldType
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> SymbolField : SPFieldMultiLineText
    {
        <span class="kwrd">public</span> SymbolField (SPFieldCollection fields, <span class="kwrd">string</span> fieldName)
            : <span class="kwrd">base</span>(fields, fieldName)
        {
            ;
        }

        <span class="kwrd">public</span> SymbolField (SPFieldCollection fields, <span class="kwrd">string</span> typeName, <span class="kwrd">string</span> displayName)
            : <span class="kwrd">base</span>(fields, typeName, displayName)
        {
            ;
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> Microsoft.SharePoint.WebControls.BaseFieldControl FieldRenderingControl
        {
            get
            {
                BaseFieldControl control = <span class="kwrd">new</span> SymbolFieldControl();
                control.FieldName = <span class="kwrd">this</span>.InternalName;
                <span class="kwrd">return</span> control;
            }
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> GetValidatedString (<span class="kwrd">object</span> <span class="kwrd">value</span>)
        {
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.Required || <span class="kwrd">value</span>.ToString().Equals(<span class="kwrd">string</span>.Empty))
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> SPFieldValidationException(<span class="str">"Symbols not assigned"</span>);
            }
            <span class="kwrd">return</span> <span class="kwrd">base</span>.GetValidatedString(<span class="kwrd">value</span>);
        }

    }
}
</pre>

<br /><br /><b>5. Die Control-Definion für den neuen Typ anlegen</b><br /><br />Die Control-Definion bestimmt das Verhalten und das Aussehen des neuen Feldes in der Editier-Ansicht. Diese Klasse ist eigentlich die &quot;Code-Behind&quot; Klasse des ascx-Files.<br /><br /><a href="javascript:openpopup('images/2009-09-22_144744.png',479,169,false);"><img src="images/2009-09-22_144744.png" width="479" height="169" border="0" alt="" /></a><br /><br />Hier wird dem Anwender eine Multi-Select Listbox angezeigt.<br /><br />SymbolFieldControl.cs Listing:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">
<span class="kwrd">using</span> System.Configuration;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Web.UI.WebControls;
<span class="kwrd">using</span> Microsoft.SharePoint.WebControls;

<span class="kwrd">namespace</span> SymbolFieldType
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> SymbolFieldControl : BaseFieldControl
    {
        <span class="preproc">#region</span> [ Protected properties          ]

        <span class="kwrd">protected</span> ListBox symbolListBox;

        <span class="preproc">#endregion</span>

        <span class="preproc">#region</span> [ Overridden methods            ]
        
        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">string</span> DefaultTemplateName
        {
            get
            {
                <span class="kwrd">return</span> <span class="str">@"SymbolFieldControl"</span>;
            }
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">object</span> Value
        {
            get
            {
                <span class="kwrd">this</span>.EnsureChildControls();
                <span class="kwrd">return</span> GetSelectedValues(<span class="kwrd">this</span>.symbolListBox);
            }
            set
            {
                <span class="kwrd">this</span>.EnsureChildControls();
                <span class="kwrd">string</span> selectedItemsString = (<span class="kwrd">string</span>)<span class="kwrd">this</span>.ItemFieldValue;
                <span class="kwrd">foreach</span> (ListItem i <span class="kwrd">in</span> symbolListBox.Items)
                {
                    <span class="kwrd">if</span> (i.Value.Length > 0 && selectedItemsString.Contains(i.Value))
                    {
                        i.Selected = <span class="kwrd">true</span>;
                    }
                }
            }
        }

        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> CreateChildControls ()
        {
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.Field == <span class="kwrd">null</span> || <span class="kwrd">this</span>.ControlMode == SPControlMode.Display)
                <span class="kwrd">return</span>;
            <span class="kwrd">base</span>.CreateChildControls();

            <span class="kwrd">this</span>.symbolListBox = (ListBox)TemplateContainer.FindControl(<span class="str">"symbolListBox"</span>);

            <span class="kwrd">if</span> (<span class="kwrd">this</span>.symbolListBox == <span class="kwrd">null</span>)
                <span class="kwrd">throw</span> <span class="kwrd">new</span> ConfigurationException(<span class="str">"SymbolFieldControl.ascx is corrupt."</span>);

            <span class="kwrd">if</span> (!<span class="kwrd">this</span>.Page.IsPostBack)
            {
                <span class="kwrd">this</span>.symbolListBox.Items.AddRange(<span class="kwrd">new</span> ListItem[]{ 
                  <span class="kwrd">new</span> ListItem(<span class="kwrd">string</span>.Empty, <span class="kwrd">null</span>), 
                  <span class="kwrd">new</span> ListItem(<span class="str">"Ätzend"</span>, <span class="str">"Aetzend.png"</span>), 
                  <span class="kwrd">new</span> ListItem(<span class="str">"Brandfördernd"</span>, <span class="str">"Brandfoerdernd.png"</span>), 
                  <span class="kwrd">new</span> ListItem(<span class="str">"Explosiv"</span>, <span class="str">"Explosiv.png"</span>), 
                  <span class="kwrd">new</span> ListItem(<span class="str">"Flammbar 1"</span>, <span class="str">"Flamm1.png"</span>),
                  <span class="kwrd">new</span> ListItem(<span class="str">"Flammbar 2"</span>, <span class="str">"Flamm2.png"</span>),
                  <span class="kwrd">new</span> ListItem(<span class="str">"Flammbar 3"</span>, <span class="str">"Flamm3.png"</span>),
                  <span class="kwrd">new</span> ListItem(<span class="str">"Giftig"</span>, <span class="str">"Giftig.png"</span>),
                  <span class="kwrd">new</span> ListItem(<span class="str">"Leicht entzündlich"</span>, <span class="str">"LeichtEntzuendlich.png"</span>),
                  <span class="kwrd">new</span> ListItem(<span class="str">"Reizend"</span>, <span class="str">"Reizend.png"</span>),
                });
                
                <span class="kwrd">this</span>.symbolListBox.SelectionMode = ListSelectionMode.Multiple;
            }
        }

        <span class="preproc">#endregion</span>

        <span class="preproc">#region</span> [ Private methods               ]

        <span class="kwrd">private</span> <span class="kwrd">string</span> GetSelectedValues (ListBox listBox)
        {
            StringBuilder selectedItems = <span class="kwrd">new</span> StringBuilder();
            <span class="kwrd">foreach</span> (ListItem item <span class="kwrd">in</span> listBox.Items)
            {
                <span class="kwrd">if</span> (item.Selected)
                {
                    selectedItems.Append(<span class="str">"<img src=\"/Pictograms/"</span>);
                    selectedItems.Append(item.Value);
                    selectedItems.Append(<span class="str">"\">"</span>);
                }
            }
            <span class="kwrd">return</span> selectedItems.ToString();
        }

        <span class="preproc">#endregion</span>
    }
}
</pre>

<br /><br />Die gewählten Einträge der ListBox werden gleich als String von HTML Image-Tags gespeichert, um später in der Listen-Ansicht nicht das Problem zu haben, dass man mit CAML die Elemente zerlegen und zusammenbauen muss *grusel*. Sicher gibt es auch schönere Ansätze, aber in diesem Fall funktioniert es auch so.<br /><br /><b>6. Das ascx-Control zum Bearbeiten des Feldes anlegen</b><br /><br />Im Ordner TEMPLATE\CONTROLTEMPLATES eine leere ascx-Datei (ohne Code-Behind) anlegen, und folgenden Codeschnipsel einfügen:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">
<span class="asp"><%@ Control Language="C#" Debug="true" %></span>
<span class="asp"><%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %></span>
<span class="asp"><%@ Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
             Namespace="Microsoft.SharePoint.WebControls" %></span>

<span class="kwrd"><</span><span class="html">SharePoint:RenderingTemplate</span> <span class="attr">ID</span><span class="kwrd">="SymbolFieldControl"</span> <span class="attr">runat</span><span class="kwrd">="server"</span><span class="kwrd">></span>
  <span class="kwrd"><</span><span class="html">Template</span><span class="kwrd">></span>
    <span class="kwrd"><</span><span class="html">asp:ListBox</span> <span class="attr">ID</span><span class="kwrd">="symbolListBox"</span> <span class="attr">runat</span><span class="kwrd">="server"</span>  <span class="kwrd">/></span>
  <span class="kwrd"></</span><span class="html">Template</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">SharePoint:RenderingTemplate</span><span class="kwrd">></span>
</pre>

<br /><br />Wenn man eigene Controls baut sollte man darauf achten, dass hier der Typ des ASP.NET controls dem Element entspricht, das man in der Field-Control Definition angegeben hat. Hier muss also zusammenpassen:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">
<span class="kwrd"><</span><span class="html">asp:ListBox</span> <span class="attr">ID</span><span class="kwrd">="symbolListBox"</span> <span class="attr">runat</span><span class="kwrd">="server"</span>  <span class="kwrd">/></span></pre>

<br /><br />und<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<pre class="csharpcode">
<span class="kwrd">protected</span> ListBox symbolListBox;</pre>

<br /><br /><b>7. Die XML-Felddefinion anlegen</b><br /><br />im Ordner TEMPLATE\XML eine leere XML-Datei anlegen, und folgendes einfügen:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<pre class="csharpcode">
<span class="kwrd"><?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">="1.0"</span> <span class="attr">encoding</span><span class="kwrd">="utf-8"</span> ?<span class="kwrd">></span>
<span class="kwrd"><</span><span class="html">FieldTypes</span><span class="kwrd">></span>
    <span class="kwrd"><</span><span class="html">FieldType</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="TypeName"</span><span class="kwrd">></span>SymbolSelection<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="ParentType"</span><span class="kwrd">></span>Note<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="SQLType"</span><span class="kwrd">></span>ntext<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="TypeDisplayName"</span><span class="kwrd">></span>Danger sign<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="TypeShortDescription"</span><span class="kwrd">></span>Custom symbol column<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="Sortable"</span><span class="kwrd">></span>FALSE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="Filterable"</span><span class="kwrd">></span>FALSE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="UserCreatable"</span><span class="kwrd">></span>TRUE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="ShowInListCreate"</span><span class="kwrd">></span>TRUE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="ShowInSurveyCreate"</span><span class="kwrd">></span>TRUE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="ShowInDocumentLibraryCreate"</span><span class="kwrd">></span>TRUE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="ShowInColumnTemplateCreate"</span><span class="kwrd">></span>TRUE<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">Field</span> <span class="attr">Name</span><span class="kwrd">="FieldTypeClass"</span><span class="kwrd">></span>SymbolFieldType.SymbolField, SymbolFieldType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=!Hier den eigenen Token einsetzen!<span class="kwrd"></</span><span class="html">Field</span><span class="kwrd">></span>
        <span class="kwrd"><</span><span class="html">RenderPattern</span> <span class="attr">Name</span><span class="kwrd">="DisplayPattern"</span><span class="kwrd">></span>
            <span class="kwrd"><</span><span class="html">Switch</span><span class="kwrd">></span>
                <span class="kwrd"><</span><span class="html">Expr</span><span class="kwrd">></span>
                    <span class="kwrd"><</span><span class="html">Column</span><span class="kwrd">/></span>
                <span class="kwrd"></</span><span class="html">Expr</span><span class="kwrd">></span>
                <span class="kwrd"><</span><span class="html">Case</span> <span class="attr">Value</span><span class="kwrd">=""</span><span class="kwrd">></span>
                <span class="kwrd"></</span><span class="html">Case</span><span class="kwrd">></span>
                <span class="kwrd"><</span><span class="html">Default</span><span class="kwrd">></span>
                    <span class="kwrd"><</span><span class="html">Column</span><span class="kwrd">/></span>
                <span class="kwrd"></</span><span class="html">Default</span><span class="kwrd">></span>
            <span class="kwrd"></</span><span class="html">Switch</span><span class="kwrd">></span>
        <span class="kwrd"></</span><span class="html">RenderPattern</span><span class="kwrd">></span>
    <span class="kwrd"></</span><span class="html">FieldType</span><span class="kwrd">></span>
<span class="kwrd"></</span><span class="html">FieldTypes</span><span class="kwrd">></span></pre>

<br /><br />Der PublicKeyToken muss mit <em>sn.exe -T MyCustomFieldType.dll</em> aus der aktuellen Assembly ermittelt werden.<br /><br /><em>Erläuterungen:</em><br /><br />&quot;ParentType&quot; gibt den internen zu verwendenen SharePoint Datentypen an. Note ist ein Text mit mehr als 255 Zeichen.<br />&quot;SQLType&quot; gibt den zu verwendenen Physikalischen Datentypen in der Datenbank an. Dies kann für den Note Typ nötig zu sein.<br /><br />Die restelichen Field-Definitionen sollten selbsterklärend sein...<br /><br />Wichtig ist natürlich der Abschnitt RenderPattern, in dem per CAML das Aussehen des Feldinhaltes in der Listenansicht und in der Detailansicht definiert wird. In diesem Beispiel wird der Inhalt einfach nur 1:1 ausgegeben, denn er ist ja bereits richtig formatiert:<br /><br />
<!-- code formatted by <a href="http://manoli.net/csharpformat/" target="_blank" >http://manoli.net/csharpformat/</a> -->
<pre class="csharpcode">
<span class="kwrd"><</span><span class="html">Default</span><span class="kwrd">></span>
    <span class="kwrd"><</span><span class="html">Column</span><span class="kwrd">/></span>
<span class="kwrd"></</span><span class="html">Default</span><span class="kwrd">></span></pre>

<br /><br /><b>8. Deployment</b><br /><br />Ohne WSP-Datei, muss alles per Hand installiert werden. Das geht jedoch wesentlich schneller!<br /><br />- Die kompilierte DLL des Projektes kommt in den GAC auf dem Webserver. Einfach mit dem Explorer hineinkopieren.<br /><br />- Die ascx-Datei kopiert man in den Ordner ...\12\TEMPLATE\CONTROLTEMPLATES<br /><br />- Und die XML-Datei kopiert man in den Ordner ...\12\TEMPLATE\XML<br /><br />Wenn man jetzt im IIS den entsprechenden Application-Pool aktualisiert (recycle), sollte der neue Feld-Typ auch schon verfügbar sein!<br /><br />Das ganze muss man bei einer Server-Farm natürlich für jeden FrontendWebServer machen. Dafür kann man sich aber eine kleine Batch-Datei schreiben...<br /><br />Um den Feld-Typen zu deinstallieren, genügt es, die Assembly aus dem GAC zu entfernen und die beiden Dateien im Filesystem zu löschen.<br /><br /><br />Quellen:<br /><a href="http://wspbuilder.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25962" target="_blank" >http://wspbuilder.codeplex.com/Release/ ... seId=25962</a><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry090922-150018</guid>
			<author>jonka</author>
			<pubDate>Tue, 22 Sep 2009 13:00:18 GMT</pubDate>
		</item>
		<item>
			<title>SharePoint 2007 - Custom List Form Attachments</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry090922-144130</link>
			<description><![CDATA[Über Custom List Forms kann man eigens angepasste Formulare für New/Edit/View für Listen oder Libraries erstellen.<br />Wenn man dann aber versucht, ein Attachment an einen Listeneintrag zu hängen, stellt man fest, dass es zunächst den einen oder anderen Fehler gibt, z.B.:<br /><br /><i>&quot;This form was customized not working with attachment&quot;</i><br /><br />oder<br /><br /><i>&quot;Can&#039;t move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus.&quot;</i><br /><br />oder der Button zum Editieren eines Elements fehlt völlig.<br /><br />Natürlich gibt es für dieses bekannte Problem schon eine Lösung:<br /><a href="http://support.microsoft.com/?scid=kb%3Ben-us%3B953271&amp;x=13&amp;y=14" target="_blank" >http://support.microsoft.com/?scid=kb%3 ... 3&amp;y=14</a><br /><br />Allerdings funktionierte es bei mir trotzdem nicht. Was war los?<br /><br />Zum Einen benötigt man dafür nicht unbedingt den angegebenen Hotfix, sondern die Installation von SP2 sollte ausreichen.<br /><br />Zum Anderen muss man darauf achten, dass man das ursprüngliche Standard-Formular<br /><br /><a href="javascript:openpopup('images/2009-09-22_142757.png',629,201,false);"><img src="images/2009-09-22_142757.png" width="484" height="155" border="0" alt="" /></a><br /><br />auf der Seite belässt aber über die WebPart-Eigenschaften <em>schließt</em>:<br /><br /><a href="javascript:openpopup('images/2009-09-22_143002.png',279,362,false);"><img src="images/2009-09-22_143002.png" width="279" height="362" border="0" alt="" /></a><br /><br /><a href="javascript:openpopup('images/2009-09-22_143104.png',317,154,false);"><img src="images/2009-09-22_143104.png" width="317" height="154" border="0" alt="" /></a><br /><br />Wenn man das alte Formular löscht, lässt sich die Seite gar nicht mehr aufrufen. Wenn man es nur versteckt, bekommt man später einen JavaScript-Fehler.<br />Da der SharePoint Designer zudem bei mir einen Fehler im WebPart-Eigenschafts-Menü hatte, so dass ich das Menü nicht sehen konnte, musste ich die Einstellung im XML vornehmen und <b>IsIncluded</b> auf <b>false</b> setzen:<br /><br /><code>&lt;IsIncluded&gt;false&lt;/IsIncluded&gt;</code><br /><br />Danach klappt es auch mit den Attachments...<br /><br /><b>Quellen:</b><br /><a href="http://support.microsoft.com/?scid=kb%3Ben-us%3B953271&amp;x=13&amp;y=14" target="_blank" >http://support.microsoft.com/?scid=kb%3 ... 3&amp;y=14</a><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry090922-144130</guid>
			<author>jonka</author>
			<pubDate>Tue, 22 Sep 2009 12:41:30 GMT</pubDate>
		</item>
		<item>
			<title>Javascript Fehler nach Installation von MOSS SP2</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry090922-115151</link>
			<description><![CDATA[Nach der Installation von SharePoint SP2 auf einem VirtualPC Entwicklungs-Image zeigte sich auf einmal das Problem, dass jegliches Submit von Formularen nicht mehr funktionierte. Es gab unterschiedliche JavaScript Fehlermeldungen beim Klick auf den Button, z.B.:<br /><br /><i>&quot;WebForm_PostBackOptions is undefined&quot;</i><br /><br />Nach langem Suchen - unter anderem gab es viele Hinweise darauf, dass es sich um ein Problem mit httpModules und WebResource.axd handeln solle - fand ich den entscheidenden Kommentar in einem Blog.<br /><br />Das Datum des VPC Images war einfach falsch! Es lag in der Vergangenheit, und MOSS SP2 mag offenbar keine falschen Zeitangaben im System - ein Schelm, wer böses dabei denkt ;)<br />Nach der Korrektur (und vorsichtshalber Neustart) lief alles wie gewohnt.<br /><br /><b>Also: Wenn dieser Fehler auftritt, zu allererst das Datum des Servers Prüfen, dann erst im IIS ISAPI-Filter verändern.<br /></b><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry090922-115151</guid>
			<author>jonka</author>
			<pubDate>Tue, 22 Sep 2009 09:51:51 GMT</pubDate>
		</item>
		<item>
			<title>SharePoint 2007 - Editierbare Themes und Vererbung auf neue Sites</title>
			<link>http://www.jonka.de/blog/index.php?entry=entry090821-154753</link>
			<description><![CDATA[Diese Themen sind zwar alles andere als neu, aber ich habe mir nochmal die Mühe gemacht, alle Schritte zusammenzutragen und aufzuschreiben, die nötig sind, um ein eigenes SharePoint Theme automatisch auf neu angelegte Sites anzuwenden und dieses Theme obendrein zur Laufzeit editierbar zu halten. (Ansonsten müsste man zum nachträglichen Ändern jede Site einzeln aktualisieren.)<br />Diese Methode ist meines Wissens nach die einzige Alternative zum Erstellen eigener, individuell gestalteter Templates - hat aber den Vorteil, dass das gesamte Portal immer noch 100% dem Standard entspricht und sich später einmal problemlos migrieren lassen sollte.<br /><br /><b>1. Custom Theme erstellen</b><br /><br /><a href="http://www.jonka.de/blog/index.php?entry=entry061017-095822" target="_blank" >Hier steht, wie man ein custom Theme nach regulärem Schema erstellt</a><br /><br />Normale Themes haben allerdings einen entscheidenen Nachteil: Wenn ein Theme einmal auf eine Site angewendet wurde, werden weitere Veränderungen am Theme nicht mehr in der Site übernommen! Wer also 1000 Sites mit eigenem Theme hat und dann feststellt, dass die CSS Datei doch noch mal geändert werden muss, hat ein Problem.<br /><br />Die beste Lösung hierzu, die im Netz gefunden habe, ist folgende:<br /><br />1.1 <br />Man erstellt einen neuen Ordner im System (z.B. &quot;Customer_Theme&quot;) unter:<br />...\12\TEMPLATE\LAYOUTS\1033\STYLES\<b>Customer_Theme</b><br />und kopiert den gesamten Inhalt des Theme-Ordners (z.B. &quot;Customer&quot;) von<br />...\12\TEMPLATE\THEMES\<b>Customer</b><br />in den neuen Ordner.<br /><br />1.2<br />Man löscht den Inhalt des alten Theme-Ordners, bis auf die beiden Dateien<br /><b>Customer.INF</b> und<br />theme.css<br /><br />1.3<br />Man editiert die theme.css und ersetzt den gesamten Inhalt durch fogende beiden Zeilen:<br /><br />@import &quot;/_layouts/1033/styles/<b>Customer_Theme</b>/mossExtension.css&quot;;<br />@import &quot;/_layouts/1033/styles/<b>Customer_Theme</b>/theme.css&quot;;<br /><br /><br />Das führt dazu, dass das Theme lediglich die beiden angegeben CSS Dateien einbindet. Das Theme braucht man danach auch nie mehr zu ändern, denn Änderungen können jetzt in dem neuen Ordner vorgenommen werden und sind sofort sichtbar!<br /><br /><br /><b>2. Projektstruktur in Visual Studio erstellen</b><br /><br />Es empfiehlt sich, folgende Projektstruktur für das weitere Vorgehen anzulegen:<br />(Ausgehend von einer standard Class-Library)<br /><br /><a href="javascript:openpopup('images/2009-08-21_150730.png',261,355,false);"><img src="images/2009-08-21_150730.png" width="261" height="355" border="0" alt="" /></a><br /><br />Die DLL muss einen Strong Name haben.<br />Die DeployTTA.bat wird nicht unbedingt benötigt.<br /><br />Alternativ kann auch mein Beispiel-Projekt verwendet werden:<br /><br /><a href="/Download/ThemeActivator2008.zip" target="_blank" >Download ThemeActivator2008.zip</a><br /><br /><b>3. ThemeActivatorReceiver.cs implementieren</b><br /><br />Dieser Part ist sehr einfach. Der unten stehende Code kann (bis auf den Namespace) 1:1 übernommen werden und muss nicht weiter angepasst werden:<br /><code><br />using System;<br />using System.Collections.Generic;<br />using System.Text;<br />using Microsoft.SharePoint;<br />using System.IO;<br />namespace <b>Company.SharePoint</b><br />{<br />    public class ThemeActivatorReceiver : SPFeatureReceiver<br />    {<br />        private const string Property_DefaultTheme = &quot;DefaultTheme&quot;;<br />        private const string Property_ThemeToApply = &quot;ThemeToApply&quot;;<br /><br />        public override void FeatureInstalled(SPFeatureReceiverProperties properties)<br />        {<br />        }<br /><br />        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)<br />        {<br />        }<br /><br />        public override void FeatureActivated(SPFeatureReceiverProperties properties)<br />        {<br />            SPSite site = properties.Feature.Parent as SPSite;<br />            SPWeb web = properties.Feature.Parent as SPWeb;<br />            if (site != null)<br />            {<br />                web = site.RootWeb;<br />            }<br />            if (web != null)<br />            {<br />                if (properties.Feature.Properties[Property_ThemeToApply] != null)<br />                {<br />                    string theme = properties.Feature.Properties[Property_ThemeToApply].Value;<br />                    if (!string.IsNullOrEmpty(theme))<br />                    {<br />                        web.ApplyTheme(theme);<br />                    }<br />                }<br />            }<br />        }<br /><br />        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)<br />        {<br />            SPSite site = properties.Feature.Parent as SPSite;<br />            SPWeb web = properties.Feature.Parent as SPWeb;<br />            if (site != null)<br />            {<br />                web = site.RootWeb;<br />            }<br />            if (web != null)<br />            {<br />                if (properties.Feature.Properties[Property_DefaultTheme] != null)<br />                {<br />                    string theme = properties.Feature.Properties[Property_DefaultTheme].Value;<br />                    if (!string.IsNullOrEmpty(theme))<br />                    {<br />                        web.ApplyTheme(theme);<br />                    }<br />                }<br />            }<br />        }<br />    }<br />}<br /></code><br />Die Information, welches Theme zu setzen ist, kommt später aus dem XML des Features.<br /><br /><br /><b>4. Theme Activator-Feature implementieren</b><br /><br />Um ein Theme automatisch auf eine Site anzuwenden, muss zunächst ein neues Feature erstellt und deployed werden, das in der Lage ist, bei seiner Aktivierung der aktuellen Site das Gewünschte Theme zu verpassen.<br />(Später wird das zweite Feature benötigt, welches automatisch das erste Feature aktiviert.)<br /><br />Hierzu die Datei ThemeActivator\feature.xml mit folgendem XML befüllen:<br /><code><br />&lt;Feature  Id=&quot;<b>86D25ADF-DE83-4238-8EFF-802AB22136C2</b>&quot;<br />          Title=&quot;<b>Customer Theme Activator</b>&quot;<br />          Description=&quot;<b>Applies the Customer Theme to this site.</b>&quot;<br />          Version=&quot;1.0.0.0&quot;<br />          Scope=&quot;Web&quot;<br />          Hidden=&quot;false&quot;<br />          DefaultResourceFile=&quot;core&quot;<br />          xmlns=&quot;http://schemas.microsoft.com/sharepoint/&quot;<br />          ActivateOnDefault=&quot;true&quot;<br />          ReceiverAssembly=&quot;<b>Company.SharePoint</b>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<b>a32a55f152c86b83</b>&quot;<br />          ReceiverClass=&quot;<b>Company.SharePoint.ThemeActivatorReceiver</b>&quot;<br />          &gt;<br />	&lt;Properties&gt;<br />		&lt;Property Key=&quot;DefaultTheme&quot; Value=&quot;none&quot; /&gt;<br />		&lt;Property Key=&quot;ThemeToApply&quot; Value=&quot;<b>Customer</b>&quot; /&gt;<br />	&lt;/Properties&gt;<br />&lt;/Feature&gt;<br /></code><br />Die hervorgehobenen Bereiche sind individuell anzupassen:<br /><br /><b>Feature Id:</b> Hier eine eigene Guid einfügen<br /><b>Feature Title:</b> Eigener Name für das Feature (wird in der Feature Übersicht angezeigt)<br /><b>Feature Description:</b> Entsprechende Beschreibung<br /><b>ReceiverAssembly:</b> Name der DLL<br /><b>PublicKeyToken:</b> Der StrongName der Assembly (über &quot;sn.exe -Tp&quot; ermitteln)<br /><b>ReceiverClass:</b> Namespace+Name der Klasse in der ThemeActivatorReceiver.cs<br /><b>Property ThemeToApply Value:</b> Name des Themes, wie er in der .INF Datei angegeben wurde<br /><br />Das Feature wird dann den Code aus dem ThemeActivatorReceiver aufrufen, und den Namen des Themes (hier &quot;Customer&quot;) übertragen.<br /><br /><br /><b>5. ThemeTemplateAssociation Feature implementieren</b><br /><br />Das zweite Feature benötigt keinen .NET Code, sondern dient lediglich dazu, beim Anlegen einer neuen Site das erste Feature aufzurufen.<br />Diese Feature ist auch nicht in der Feature Übersicht sichtbar, sondern ist automatisch aktiv.<br /><br />In [u]ThemeTemplateAssociation\feature.xml[/u] folgenden Code einfügen:<br /><code><br />&lt;Feature  Id=&quot;<b>FC472661-DE52-4fda-950A-970ED9EAE9E5</b>&quot;<br />          Title=&quot;<b>Customer Theme Stapling</b>&quot;<br />          Description=&quot;<b>Staples the Customer Theme Feature to all sites.</b>&quot;<br />          Version=&quot;1.0.0.0&quot;<br />          Scope=&quot;Farm&quot;<br />          Hidden=&quot;true&quot;<br />          DefaultResourceFile=&quot;core&quot;<br />          xmlns=&quot;http://schemas.microsoft.com/sharepoint/&quot;<br />          ActivateOnDefault=&quot;true&quot;<br />          &gt;<br />	&lt;ElementManifests&gt;<br />		&lt;ElementManifest Location=&quot;SiteAssociations.xml&quot; /&gt;<br />	&lt;/ElementManifests&gt;<br />&lt;/Feature&gt;<br /></code><br />Die hervorgehobenen Bereiche wie zuvor entsprechend anpassen.<br /><br />Danach in die ThemeTemplateAssociation\SiteAssociations.xml folgenden Inhalt einfügen:<br /><code><br />&lt;Elements xmlns=&quot;http://schemas.microsoft.com/sharepoint/&quot;&gt;<br />	&lt;!-- &lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;GLOBAL#0&quot; /&gt; --&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSMSITE#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSPERS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;OSRV#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;STS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;STS#1&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;STS#2&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;MPS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;MPS#1&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;MPS#2&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;MPS#3&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;MPS#4&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;WIKI#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;BLOG#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;BDR#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;EAWF#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;OFFILE#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;OFFILE#1&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;PWA#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;PWS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSMSITE#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSTOC#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSTOPIC#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSNEWS#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSNHOME#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSSITES#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSBWEB#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSCOMMU#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSREPORTCENTER#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SPSPORTAL#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;SRCHCEN#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;PROFILES#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;CMSPUBLISHING#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;BLANKINTERNET#0&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;BLANKINTERNET#1&quot; /&gt;<br />	&lt;FeatureSiteTemplateAssociation Id=&quot;86D25ADF-DE83-4238-8EFF-802AB22136C2&quot; TemplateName=&quot;BLANKINTERNET#2&quot; /&gt;<br />&lt;/Elements&gt;<br /></code><br />Die Angegebene Guid in jeder Zeile muss mit der Guid aus dem XML des ThemeActivator-Feature übereinstimmen.<br />Jede Zeile steht hier für einen Vorgegebenen Template Typ aus SharePoint, bei dessen Verwendung das Feature mit der Guid aktiviert wird.<br />Die auskommentierte Zeile mit GLOBAL#0 soll eigentlich alle Template-Typen mit einschließen, aber scheinbar funktioniert das nicht wie erwartet. Darum ist hier jeder Typ einzeln aufgelistet.<br /><br /><br /><b>6. Das Installations-Batch erstellen</b><br /><br />Der Inhalt der Install.bat sollte folgendermaßen aussehen:<br /><code><br />@SET TEMPLATEDIR=&quot;C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE&quot;<br />@SET STSADM=&quot;C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm&quot;<br />@SET GACUTIL=&quot;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil&quot;<br />%GACUTIL% -if bin\debug\<b>Company.SharePoint.dll</b><br />xcopy /e /y TEMPLATE\* %TEMPLATEDIR%<br />%STSADM% -o InstallFeature -filename ThemeActivator\feature.xml -force<br />%STSADM% -o InstallFeature -filename ThemeTemplateAssociation\feature.xml -force<br />IISRESET<br /></code><br />Im Grunde wird hier nur die DLL des Projektes in den GAC kopiert, die beiden Feature-Verzeichnisse in das FEATURES Verzeichnis von SharePoint kopiert und die beiden Features werden über stsadm.exe installiert.<br /><br /><br /><b>7. Deployment</b><br /><br />Anschließend das Projekt kompilieren, und über den Explorer die Install.bat aufrufen. Damit sollte alles erledigt sein.<br />Die Install.bat muss natürlich auf dem SharePoint Server selbst ausgeführt werden. Wenn man nicht dort entwickelt hat, am besten alles erstmal dorthin kopieren.<br /><br />Anschließend sollte in SharePoint das neue &quot;Customer Theme Activator&quot; Feature sichtbar sein. Beim Erstellen einer neuen Site sollte jetzt auch bereits das angegebene Theme verwendet werden und das Feature automatisch aktiv sein.<br />Wenn dies nicht der Fall ist, wurde evtl. ein Template verwendet, das nicht der SiteAssociations.xml definiert wurde. Am besten man probiert es zunächst mit &quot;Blank&quot; und &quot;Teamsite&quot;.<br /><br />Wenn auf dem Server entwickelt wird, kann man sich auch ganz gewöhnlich mit VisualStudio an den w3wp prozess hängen und den Aufruf des ThemeActivatorReceiver debuggen.<br /><br /><br /><br />So, und jetzt warten wir auf SharePoint 2010 und hoffen, dass dort alles viel einfacher wird, und wir all diese Merkwürdigkeiten nicht mehr benötigen.<br /><br />Quellen:<br /><a href="http://www.heathersolomon.com/blog/archive/2008/01/30/SharePoint-2007-Design-Tip-Import-your-CSS-for-SharePoint-Themes.aspx" target="_blank" >http://www.heathersolomon.com/blog/arch ... hemes.aspx</a><br /><a href="http://grahamsibley.typepad.com/thoughtfactory/2007/06/automatically_a.html" target="_blank" >http://grahamsibley.typepad.com/thought ... lly_a.html</a><br /><a href="http://www.grahamzero.com/blog/2008/05/dynamic-staplin.html" target="_blank" >http://www.grahamzero.com/blog/2008/05/ ... aplin.html</a><br />]]></description>
			<category></category>
			<guid isPermaLink="true">http://www.jonka.de/blog/index.php?entry=entry090821-154753</guid>
			<author>jonka</author>
			<pubDate>Fri, 21 Aug 2009 13:47:53 GMT</pubDate>
		</item>
	</channel>
</rss>


