Сегодня столкнулся с проблемой при разработке одного модуля на sharepoint 2007. Очень нужно сделать поле выбора который бы брал свои значения из другого списка, причем уникальные. Стандартного такого нету, в интернете поиск тоже ничего не дал. Потратил 3 часа и проект готов. Рассмотрим что получилось.
1) Создаем пустой проект под Sharepoint
2) Добавляем CustomFieldType из шаблонов WSPBuilder
3) Нам нужны 3 переменные "WEB_URL", "LIST_NAME", "FIELD_NAME"
WEB_URL = путь к узлу где находится LIST_NAME = список , и FIELD_NAME = поле списка значения которого будут использованы.
В фале fldtypes_DistinctFieldValuesFieldType.xml укажем эти 3 переменные:
<Fields>
<Field Hidden="TRUE" Name="WEB_URL" DisplayName="Web URL" Type="Text" MaxLength="500" > </Field>
<Field Hidden="TRUE" Name="LIST_NAME" DisplayName="List Name" Type="Text" MaxLength="255" > </Field>
<Field Hidden="TRUE" Name="FIELD_NAME" DisplayName="Field Name" Type="Text" MaxLength="255" > </Field>
</Fields>
Так же подредактируем сам Editor.
<wssuc:InputFormControl runat="server"
LabelText="Параметры выбора" >
<Template_Control>
<table>
<tr><td class="ms-authoringcontrols"><asp:Label id="lblurl" runat="server" Visible="True" Text="URL узла"/></td></tr>
<tr><td><asp:TextBox ID="txturl" runat="server" CssClass="ms-input" Columns="35"></asp:TextBox></td></tr>
<tr><td class="ms-authoringcontrols"><asp:Label id="lbllist" runat="server" Visible="True" Text="Название списка"/></td></tr>
<tr><td><asp:TextBox ID="txtlist" runat="server" CssClass="ms-input" Columns="35"></asp:TextBox></td></tr>
<tr><td class="ms-authoringcontrols"><asp:Label id="lblfield" runat="server" Visible="True" Text="Название поля"/></td></tr>
<tr><td><asp:TextBox ID="txtfield" runat="server" CssClass="ms-input" Columns="35"></asp:TextBox></td></tr>
</table>
</Template_Control>
</wssuc:InputFormControl>
И код:
public class DistinctFieldValuesFieldTypeFieldEditor : UserControl, IFieldEditor
{
// Fields
protected TextBox txturl;
protected TextBox txtlist;
protected TextBox txtfield;
private DistinctFieldValuesFieldType _DistinctFieldValuesFieldType;
public void InitializeWithField(SPField field)
{
this._DistinctFieldValuesFieldType = field as DistinctFieldValuesFieldType;
if (this.Page.IsPostBack)
{
return;
}
if (_DistinctFieldValuesFieldType != null)
{
this.txturl.Text = _DistinctFieldValuesFieldType.WEB_URL;
this.txtlist.Text = _DistinctFieldValuesFieldType.LIST_NAME;
this.txtfield.Text = _DistinctFieldValuesFieldType.FIELD_NAME;
}
}
public void OnSaveChange(SPField field, bool bNewField)
{
DistinctFieldValuesFieldType fld = (DistinctFieldValuesFieldType)field;
fld.IsNew = bNewField;
fld.WEB_URL = this.txturl.Text.Trim();
fld.LIST_NAME= this.txtlist.Text.Trim();
fld.FIELD_NAME= this.txtfield.Text.Trim();
}
// Properties
public bool DisplayAsNewSection
{
get
{
return false;
}
}
}
Собственно и код
public class DistinctFieldValuesFieldTypeControl : BaseFieldControl
{
private DistinctFieldValuesFieldType field;
private DropDownList ddlist;
public DistinctFieldValuesFieldTypeControl(DistinctFieldValuesFieldType parentField)
{
this.field = parentField;
}
protected override void CreateChildControls()
{
base.CreateChildControls();
try
{
ddlist = new DropDownList();
ddlist.CssClass = "ms-long DistinctFieldValuesFieldType_" + this.field.Id;
ddlist.Attributes.Add("DistinctFieldValuesFieldType", this.field.Id.ToString());
//добавим класс и аттрибут DistinctFieldValuesFieldType чтобы с помощью javascript можно было манипулировать котролом.
if(!this.field.Required)
{
ddlist.Items.Add(new ListItem("Нет",""));
}
if (!string.IsNullOrEmpty(this.field.WEB_URL) && !string.IsNullOrEmpty(this.field.LIST_NAME) && !string.IsNullOrEmpty(this.field.FIELD_NAME))
{
SPSecurity.RunWithElevatedPrivileges(
delegate
{
using (SPSite site = new SPSite(this.field.WEB_URL))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[this.field.LIST_NAME];
if (list.Fields.ContainsField(this.field.FIELD_NAME))
{
SPField groupFld = list.Fields[this.field.FIELD_NAME];
if (groupFld.Type != SPFieldType.Text & groupFld.Type != SPFieldType.Boolean & groupFld.Type != SPFieldType.Number & groupFld.Type != SPFieldType.DateTime & groupFld.Type != SPFieldType.Currency)
{throw new Exception("Cannot get distinct values.Type is not Text, Number, Currency, DateTime, or Boolean.");}
object[,] columnItems;
uint numberValues = list.GetDistinctFieldValues(groupFld, out columnItems);
for (int j = 0; j < numberValues; j++)
{
string uniqValue = SPEncode.HtmlEncode(columnItems.GetValue(0, j).ToString());
ddlist.Items.Add(uniqValue);
}
}
}
}
});
}
this.Controls.Add(ddlist);
}
catch (Exception ex)
{
Label lblerror=new Label();
lblerror.Text = ex.Message;
lblerror.Style.Add("color","red");
this.Controls.Add(lblerror);
}
}
public override object Value
{
get
{
EnsureChildControls();
if (this.ddlist != null)
return this.ddlist.SelectedValue;
else return string.Empty;
}
set
{
EnsureChildControls();
if (this.ddlist != null && value != null && !string.IsNullOrEmpty(value.ToString()))
{
this.ddlist.Text= value.ToString();
}
}
}
public override void Validate()
{
base.Validate();
if (Field.Required &&
(Value == null || Value.ToString().Length == 0))
{
this.ErrorMessage = Field.Title + " Необходимо задать значение для этого обязательного поля.";
IsValid = false;
return;
}
}
}
:
Собственно что у нас получилось: