SharePoint 2010でリストのカスタムフィルターを作成する

この記事では、標準のSharePointリスト( XsltListWebPartまたはListWebPartからの継承者)から選択できるユニバーサルフィルターを作成するために必要なすべての手順を一貫して説明します。



開発はVisual Studio 2010で行われましたが、これはSharePoint 2010でのみ動作するため、以下で説明するすべてがSharePoint Foundation 2010プラットフォームでテストされましたが、ほとんどの場合、すべてがSharePoint 2007WSS 3.0 )に当てはまります



開発環境のインストールと展開のプロセスについては説明しません。インターネットで簡単に見つけることができますが、標準リストをフィルタリングする方法の良い明確な例は見つかりませんでした。



したがって、最小タスク: 共有ドキュメントリストを次のようにフィルタリングできるWebPartを作成します。



image



つまり 使用可能なリストフィールド(表示されるだけでなく)の1つを選択し、可能な比較演算子(等しい、等しくない、より大きい、より小さいなど)の1つと実際の値を指定できます。 [ Go ]ボタンをクリックすると、リストの内容が条件を満たしている必要があります。



まず、一般的なSharePoint WebPartがどのように相互作用するかを見ていきます 。 2つ以上のWebPartsの相互作用の標準的な方法は、いわゆるプロバイダー - コンシューマーメカニズムです。



最初に、通信が実行されるインターフェースが定義されます。



インターフェースの例

public interface ITextBoxString

{

string TextBoxString { get ; set ; }

}









コンシューマは、いわゆるエントリポイントを公開します(実際、これらのメソッドはパラメータとして何らかのインターフェイスを取り、 ConnectionConsumer属性でマークされます)。



消費者の例

public class StringConsumer : WebPart

{

private ITextBoxString _myProvider;

private Label _myLabel;



protected override void OnPreRender( EventArgs e)

{

EnsureChildControls();

if (_myProvider != null )

_myLabel.Text = _myProvider.TextBoxString;

}



protected override void CreateChildControls()

{

Controls.Clear();

_myLabel = new Label{Text = "Default text" };

Controls.Add(_myLabel);

}



[ConnectionConsumer( "String Consumer" , "StringConsumer" )]

public void TextBoxStringConsumer(ITextBoxString provider)

{

_myProvider = provider;

}

}









プロバイダーは発信ポイント( ConnectionProvider属性でマークされたインターフェイスを返すメソッド)を公開します。



プロバイダーの例

public class StringProvider : WebPart, ITextBoxString

{

private TextBox _myTextBox;



[Personalizable]

public string TextBoxString { get { return _myTextBox.Text; } set { _myTextBox.Text = value ; } }



protected override void CreateChildControls()

{

Controls.Clear();

_myTextBox = new TextBox();

Controls.Add(_myTextBox);

Controls.Add( new Button {Text = "Change Text" });

}



[ConnectionProvider( "Provider for String From TextBox" , "TextBoxStringProvider" )]

public ITextBoxString TextBoxStringProvider()

{

return this ;

}

}








プロバイダーコンシューマーの通信ポイントのインターフェースが一致すれば、通信を確立できます。 さらに、対応するWebPartをページに配置した後、[ 接続 ]メニュー項目でWebPartの 1つを選択することにより、それらをリンクできます。 接続が確立された後-各ページの更新(レンダリング)の後、最初にProviderメソッド( TextBoxStringProvider )が呼び出されてインターフェイスが取得され、結果がConsumerメソッド( TextBoxStringConsumer )に渡されます。 原則として、すべてがシンプルです。 この学術的な例は、MSDNでも説明されています。



ただし、 XsltListWebPartまたはListWebPartからの継承者に対して、事前定義されたConsumerに独自のプロバイダー、つまりWebPartを記述する必要があります。 これを行うには、サポートする通信インターフェイスとそれらの操作方法を知る必要があります。 奇妙に思えるかもしれませんが、この情報はインターネット上では非常に少ないです。 原則として、この問題を解決するソリューションはほとんどありません(1つのオープンソースではなく、2つの商用プロジェクト( KWizCom List Filter PlusRoxority FilterZen Filter )が見つかりました )。



慎重な分析とリバースエンジニアリングにより、接続できるインターフェイスが2つあることが示されました: ITransformableFilterValuesIWebPartParametersです。



最初のITransformableFilterValuesインターフェースを使用すると、リストのフィールドを1つだけ選択できます(複数の場合がありますが、一度に見つかりませんでした)。プロバイダーとリストの間で接続が確立されたときに選択されます。 e。操作「等しい」のみを実装することが可能です。 したがって、このパスは私たちには適していません。



IWebPartParametersの2番目のインターフェイスは、最初にすべてのリストフィールドのリストを簡単に取得できるという点で興味深いです。



IWebPartParameters

public void SetConsumerSchema(PropertyDescriptorCollection schema)

{

Owner.Parameters = schema;

}









次に、どのフィールドがフィルタリングされるかを示す必要がありません。 GetParametersDataメソッドでは、フィールド名のペアを持つ辞書が渡されます-選択の値:



IWebPartParameters

public void GetParametersData(ParametersCallback callback)

{

var objParameters = new StateBag();

if (Owner._searchBox != null && ! string .IsNullOrEmpty(Owner._searchBox.Text))

{

objParameters.Add(Owner._comboBox.SelectedItem.Value, Owner._searchBox.Text);

}

callback(objParameters);

}








さらに、この方法で設定されたフィルターは、ユーザーが手動で作成した列のフィルターに似ています(列は、フロアが選択されたことを示すフィルターアイコンで強調表示されます)。 しかし、残念ながら、この方法も私たちには適していない。なぜなら、 選択パラメーターの厳密な同等性によってのみデータを選択できます。



どうする? 別の方法で別のWebPartに影響を与えることができます-適切なタイミングで(選択する前に)このWebPartのパラメーターを変更するだけです。



適切な時点はOnLoadイベントです。これは、ページがロードされた後、データがフェッチされる前に発生します。 変数パラメーターは、 XlstListWebPartのXmlDefinitionプロパティとListWebPartの ListViewXmlに格納されているリストのXml記述です。 このXML記述には、とりわけ、必要な条件を挿入できるデータを選択するためのCAMLリクエストがあります。



コードサンプル

private string CreateQuery()

{

if (_searchBox != null && ! string .IsNullOrEmpty(_searchBox.Text))

return String .Format( "<{1}><FieldRef Name='{0}'/><Value Type='Text'>{2}</Value></{1}>" ,

_comboBox.SelectedItem.Value, _searchType.SelectedItem.Value, _searchBox.Text);

else

return "" ;

}



protected override void OnLoad( EventArgs e)

{

base .OnLoad(e);



var query = CreateQuery();

if (query == "" ) return ;

var part = WebPartManager.WebParts[0] as XsltListViewWebPart;

if (part == null ) return ;



var doc = new XmlDocument ();

doc.LoadXml(part.XmlDefinition);

var queryNode = doc.SelectSingleNode( "//Query" );

if (queryNode == null ) return ;



var whereNode = queryNode.SelectSingleNode( "Where" );

if (whereNode != null ) queryNode.RemoveChild(whereNode);



var newNode = doc.CreateNode( XmlNodeType .Element, "Where" , String .Empty);

newNode.InnerXml = query;

queryNode.AppendChild(newNode);

part.XmlDefinition = doc.OuterXml;

}











ここでは、原則として、さらなる開発のためにそこから構築できるものです。 忘れないように、メモとして自分用に記事を書きました。 誰かがそれも役に立つことを願っています。




All Articles