6

私は、サイトコレクション全体を通して少数のリストに使用されていたサイトコンテンツタイプを持っています。そのコンテンツタイプでは、ItemAddingイベントを処理するイベントレシーバーについて説明します。これは正常に動作します。これでItemUpdatingも処理できるようにコンテンツタイプを更新する必要があります。 OTTOMH、簡単にバージョンを追跡できるように思えたので、コンテンツタイプのXMLを単純に変更しようとしました。これは、私の更新がサイトのコンテンツタイプに適用されたが、このコンテンツタイプを使用していた私のリストには適用されなかったという意味で機能しました。これは多くのことが期待された。あなたがインストールされ を持っており、その内容 タイプをアクティブにした後、どのような状況下では既に展開されているSharePointコンテンツタイプを更新して、追加のアイテムイベントを処理します。

はあなたがコンテンツタイプのコンテンツタイプ定義 ファイルを更新 必要があります。そして、私は、SharePoint SDKは、そのgrim viewを取ることに気づきました。 Windows SharePoint Servicesは コンテンツに加えられた変更を追跡しません 型定義ファイル。したがって、 には、 のサイトコンテンツタイプの変更を子コンテンツタイプ にプッシュダウンする方法がありません。

SDKは、UIまたはコードを使用して変更をプッシュする方法を説明する2つのセクションを示しています。 UIはイベント受信者にフックを提供しないので、私はコードパスを選択すると思います。

私はこのような何かを、ちょうどコンテンツタイプのリストのコピーに新しいイベントレシーバーを追加することができるだろうと思った:

SPList list = web.Lists["My list"]; 
SPContentType ctype = list.ContentTypes["My content type"]; 
// Doesn't work -- EventReceivers is null below. 
ctype.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
         "My assembly name", "My class name"); 

しかし、漁獲量がctype.EventReceiversがここにnullであるということです私はItemAddingを既にこのリストにフックアップしています。それはリスト自体に移動されたようです。したがって、リストには有効なEventReceiversコレクションがあります。だから、

SPList list = web.Lists["My list"]; 
list.EventReceivers.Add(SPEventReceiverType.ItemUpdating, 
         "My assembly name", "My class name"); 

、私はカップルの質問がある:

  1. はちょうど直接リストに新しいイベントレシーバーを追加し、ちょうど完全に私のコンテンツタイプを忘れるこれを行うには正しい方法ですか?
  2. この変更を行うには、これを構成管理の点でどのように処理するのが最適ですか?適切なリストをすべて見つけてそれぞれを変更するための簡単なコンソールアプリケーションを作成する必要がありますか?または、何らかの形でFeatureをより良い選択肢にしていますか?いずれにしても、この変更は独自のものではなく、このコンテンツタイプで作業する必要のある将来の開発者によって発見するのが難しいようです。
+0

良い質問:私は類似のものを尋ねることを意味してきました。 –

答えて

2

EventReceiverの追加後にctype.Update(true)を呼び出しましたか?もしあなたがそうしなければ、永続化されません。 Listコンテンツタイプを使用しないで、代わりにSPWeb.ContentTypesを使用してください。

このコードは、私の作品:

var docCt = web.ContentTypes[new SPContentTypeId("0x0101003A3AF5E5C6B4479191B58E78A333B28D")]; 
//while(docCt.EventReceivers.Count > 0) 
// docCt.EventReceivers[docCt.EventReceivers.Count - 1].Delete(); 
docCt.EventReceivers.Add(SPEventReceiverType.ItemUpdated, "ASSEMBLYNAME, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c5b857a999fb347e", "CLASSNAME"); 

docCt.Update(true); 

trueパラメータは、それが同様にすべての子contenttypesのにプッシュダウンされることを意味します。 (すなわち、コンテンツタイプを使用するすべてのリストに対して)。

+0

私は、SDKがコンテンツタイプの定義に触れないことを暗示した後も、その道を辿ることさえなかったと思います。私は今、あなたが明示的に変更をプッシュするように指示できるので、これは異なっていることが分かります。これはそれを行うための完璧な方法のようです。やってみます。ありがとう!さて、どのように構成管理の点でこれを行うのですか? :) –

+0

CType defに触れてはいけないのは本当です。しかし、それはそれを作成するために使用されたCAMLのみを意味します。オブジェクトモデルを通じて、あなたが好きなことをすることができます。上記のコードは、cType defsを保持するフィーチャーに結合されたフィーチャー・レシーバーを介して実行されます。 while ... deleteが追加され、私たちが必要とする回数だけ機能を無効/有効にし、cTypeごとに1つのイベントレシーバーを常に保持することができます(IMHOは最もきれいな方法です)。 あなたの質問にお答えしますか? – Colin

0

質問の第2部分までは、過去の同様の状況で行ったことを伝えたいと思いました。私たちの状況では、コンテンツタイプの更新をすべてのWebのすべてのリストに伝えることができるものと、マスターページ/ページレイアウトをサイト定義(カスタマイズされていないフォーム)。

そこで、これらのアクションごとにいくつかのカスタムstsadmコマンドを作成しました。この方法は、スクリプトをソース管理に置くことができ、既存のstsadmインタフェースを実装するので便利です。

Custom SharePoint stsadm Commands

1

は、あなたの質問の後半部分に答えるために、ためにcontenttypesのに変わるという事実のこのトリッキーな事sitecollection won't使用it'sリストにプッシュダウンします。基本的には、 "コピー"は、サイトコレクション内のフィールドで構成されており、コンテンツタイプをリストに追加すると、それらの間にリンクはありません。これは、あなたがsitecollectionに影響を与えることなくリストに変更を加えなければならないという事実によると思います。とにかくこの "問題"への私の貢献、そして私がそれをどのように解決したかは、xmlを "マスター"にすることを含み、xmlをプルして、contenttypeが使われる場所をすべて見つけ、contenttypes fieldrefs)をリストレベルで使用して、xmlのものと一致させます。

var elementdefinitions = properties.Feature.Definition.GetElementDefinitions(); 

foreach (SPElementDefinition elementDefinition in elementdefinitions) 
{ 
    if (elementDefinition.ElementType == "ContentType") 
    { 
    XmlNode ElementXML = elementDefinition.XmlDefinition; 

    // get all fieldrefs nodes in xml 
    XmlNodeList FieldRefs = ElementXML.ChildNodes[0].ChildNodes; 

    // get reference to contenttype 
    string ContentTypeID = ElementXML.Attributes["ID"].Value.ToString(); 
    SPContentType ContentType = 
     site.ContentTypes[new SPContentTypeId(ContentTypeID)]; 

    // Get all all places where the content type beeing used 
    IList<SPContentTypeUsage> ContentTypeUsages = 
     SPContentTypeUsage.GetUsages(ContentType); 
    } 
} 

次のことが(ID属性によって行われる)のリストとそれらが等しいことを確認することにあるフィールドを使用してXML XMLでfieldrefsを比較することです:コードは次のようになります。残念ながら、SPFieldLinkクラス(fieldref)のすべてのものを更新することはできません。ここでは、実際にリフレクションを使用してこれらの値を更新しています(例:ShowInEditForm)。

+0

良いコードですが、itemeventreceiverの追加に完全には関連していません。+1 + – Colin

+0

@Colin - Nah、コンテンツタイプの変更の更新に関連しています。イベントレシーバーの追加は既に私が思った –

関連する問題