Създайте персонализиран филтър за списък в SharePoint 2010
Тази статия ще опише последователно всички стъпки, необходими за написването на универсален филтър, който ви позволява да избирате от стандартни списъциSharePoint(наследници отXsltListWebPartилиListWebPart).
Разработката е извършена наVisualStudio 2010, който може да работи само сSharePoint 2010, така че всичко описано по-долу е тествано на платформатаSharePoint Foundation 2010, но най-вероятно всичко ще бъде вярно заSharePoint 2007(WSS 3.0). Няма да описвам процеса на инсталиране и внедряване на средата за разработка - лесно се търси в Интернет, но не намерих тук добри и разбираеми примери за това как да филтрирате стандартните списъци.
И така, минималната задача: СъздайтеWebPart, който може да филтрира списъкаСподелени документипо този начин:
Тези. можете да изберете едно от наличните полета в списъка (не само видимите), да посочите един от възможните оператори за сравнение (равно, не е равно, по-голямо от, по-малко от и т.н.) и действителната стойност. Когато щракнете върху бутонаОтиди, съдържанието на списъка трябва да отговаря на нашето условие.
Нека първо разгледаме как по принципWebPartнаSharePointмогат да взаимодействат помежду си. Стандартният метод за взаимодействие между две или повечеWebPartе така нареченият механизъмДоставчик-Потребител.
В началото се определя определен интерфейс, през който ще се осъществява комуникацията.
Consumerпубликува така наречените входни точки (всъщност това са методи, които приемат някакъв интерфейс като параметър и са маркирани с атрибутаConnectionConsumer).
публичен клас StringConsumer : WebPart private ITextBoxString _myProvider; частен етикет_myLabel;
защитено заместване void OnPreRender( EventArgs e) EnsureChildControls(); if (_myProv >null ) _myLabel.Text = _myProvider.TextBoxString; >
защитена отмяна void CreateChildControls() Controls.Clear(); _myLabel = нов етикет; Controls.Add(_myLabel); >
[ConnectionConsumer( "String Consumer" , "StringConsumer" )] public void TextBoxStringConsumer(ITextBoxString provider) _myProv > > >
Доставчикпубликува изходни точки (методи, възвръщащ интерфейс и посочен атрибутConnectionProvider).
публичен клас StringProvider : WebPart, ITextBoxString private TextBox _myTextBox;
защитена отмяна void CreateChildControls() Controls.Clear(); _myTextBox = ново текстово поле(); Controls.Add(_myTextBox); Controls.Add(нов бутон); >
[ConnectionProv >"Доставчик за низ от TextBox" , "TextBoxStringProvider" )] публичен ITextBoxString TextBoxStringProvider() върне това ; > >
Връзката може да бъде инсталирана, ако интерфейсите в точната връзкаДоставчикиПотребителса свързани. При това след поставяне на съответните WebPart’ове на страницата, те могат да бъдат свързани помежду си, изберете в точката на менютоConnectionедин отWebPart’ов. След като връзката е установена – след всяко обновяване (рендеринг) страниците първо ще бъдат извиквани методProvider’а (TextBoxStringProvider) за получаване на интерфейс и резултатът ще бъде предаден в методConsumer’а (TextBoxStringConsumer). В принципе всичко просто. Този академичен пример дори е описан в MSDN.
Въпреки това трябва да напишем собствен доставчик към предопределенияConsumer’у, а именноWebPart’съм, наследницитеотXsltListWebPartилиListWebPart. За целта трябва да знаем какви комуникационни интерфейси поддържат и как да работим с тях. Тази информация, колкото и да е странно, е изключително оскъдна в интернет. Както по принцип, има няколко решения, които решават този проблем (намерих два комерсиални проекта (KWizCom List Filter Plus и Roxority FilterZen Filter) и нито един с отворен код).
Усилен анализ и обратно инженерство показаха, че има два интерфейса, които могат да бъдат свързани към:ITransformableFilterValuesиIWebPartParameters.
С помощта на първия интерфейсITransformableFilterValuesе възможно да се филтрира само по едно поле на списък (евентуално по няколко, но не разбрах как направо), избрано при установяване на връзка между нашия доставчик и списъка, и само по пълното съответствие на стойността на полето с филтрираната стойност (т.е. можете да приложите само операцията „равно“). Така че този път не ни устройва.
Вторият интерфейсIWebPartParametersе интересен, защото, първо, ви позволява лесно да получите списък с всички полета на списъка:
public void SetConsumerSchema(PropertyDescriptorCollection schema) Owner.Parameters = schema; >
И второ, не изисква указание кои / кои полета са филтрирани. В методаGetParametersDataсе предава речник с двойки име-стойност на полето за избор:
Освен това филтърът, зададен по този начин, е подобен на филтъра по колони, направен ръчно от потребителя (колоните дори ще бъдат маркирани с икона за филтър, което показва, че е направен избор за този пол). Но, уви, този метод също не ни подхожда, защото. ви позволява да избирате данни само чрез строго равенство на параметрите за избор.
Какво да правя? Оказа сеМожете да повлияете на другаWebPartпо друг начин - просто като промените параметрите на тазиWebPartв точното време (преди избора).
Добър момент би било събитиетоOnLoad- което се извиква след зареждане на страницата, но преди данните да бъдат извлечени. Променливият параметър ще бъде XML описанието на списъка, което се съхранява в свойствотоXmlDefinitionзаXlstListWebPartиListViewXmlзаListWebPart. Това Xml описание, наред с други неща, има CAML заявка, в която можете да вмъкнете условията, от които се нуждаем, за да изберем данни:
защитена замяна void OnLoad( EventArgs e) база .OnLoad(e);
var query = CreateQuery(); if (query == "" ) return ; променлива част = WebPartManager.WebParts[0] като XsltListViewWebPart; if (part == null) return;
var doc = нов XmlDocument(); doc.LoadXml(part.XmlDefinition); var queryNode = doc.SelectSingleNode( "//Query" ); if (queryNode == null) return;
var whereNode = queryNode.SelectSingleNode( "Къде"); if (whereNode != null ) queryNode.RemoveChild(whereNode);
var newNode = doc.CreateNode( XmlNodeType .Element, "Where" , String .Empty); newNode.InnerXml = заявка; queryNode.AppendChild(newNode); part.XmlDefinition = doc.OuterXml; >
Това е основно това, от което можете да започнете за по-нататъшно развитие. Написах статия за себе си като напомняне, за да не забравя. Надявам се да е полезно и за някого.
Hardcore conf в C++. Каним само професионалисти.