Hower she was not that impressed by the result. She wanted the field to show an extra asterix. The field was after all required!
Then again without a notice she returned with a requirement that there should be added a description if needed...
I tried to add som html at various places in my pagelayout realising the result was not that good :-)
The the customer returned with an ather requirement... "Any text is displayed in the language the user pleaces".
I realized this was the end of doing minor tweeks in the html...
I started to investgate my pagelayout finding that I wanted something simmilar to the standard Sharepoint Web Control (Microsoft.SharePoint.WebControls).
I wanted to add required indicator, decription text or, - not display anything (I guess my customer will return)
Like this:
No more talking do some coding:
I created a class that inherits TextField Control
The the customer returned with an ather requirement... "Any text is displayed in the language the user pleaces".
I realized this was the end of doing minor tweeks in the html...
I started to investgate my pagelayout finding that I wanted something simmilar to the standard Sharepoint Web Control (Microsoft.SharePoint.WebControls).
<sharepointwebcontrols:userfield fieldname="PublishingContact" id="eUserFieldContact" runat="server" />
I wanted to add required indicator, decription text or, - not display anything (I guess my customer will return)
Like this:
<webcontrols:textfield description="..." descriptioncssclass="edit-mode-field-description" fieldname="PublishingContact" hidetitle="False" id="eTextFieldTitle" requiredtext="*" requiredtextcssclass="edit-mode-required-field-marker" runat="server" title="..." />
Having learned a Sharepoint lesson or two I also figured I could need an extra Title field to override default text.No more talking do some coding:
I created a class that inherits TextField Control
public class TextField : Microsoft.SharePoint.WebControls.TextField, IBaseFieldControl
{
public bool HideTitle { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DescriptionCssClass { get; set; }
public string RequiredText { get; set; }
public string RequiredTextCssClass { get; set; }
protected override void Render(HtmlTextWriter output)
{
if (!HideTitle)
this.RenderCustom(output);
else
{
DisableInputFieldLabel = true;
base.Render(output);
}
}
public void RenderFieldForCustomInput(HtmlTextWriter output)
{
RenderFieldForInput(output);
}
}
{
public bool HideTitle { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DescriptionCssClass { get; set; }
public string RequiredText { get; set; }
public string RequiredTextCssClass { get; set; }
protected override void Render(HtmlTextWriter output)
{
if (!HideTitle)
this.RenderCustom(output);
else
{
DisableInputFieldLabel = true;
base.Render(output);
}
}
public void RenderFieldForCustomInput(HtmlTextWriter output)
{
RenderFieldForInput(output);
}
}
and an interface mathing the requirement.
I Also creatd a RenderCustom Extention method to render the label ++
Now I thought I was good to go, but i spoke too soon... My customer wanted the same feature for the Taxonomy control. Great another inherit... Well, this time Microsoft was so nice that they planned for this crazy requirement. The made the TaxonomyFieldControl sealed. Using Reflector and som guess I wrapped the field using the same IBaseFieldControl interface. Whola! A fully working Taxonomy Field...
At the end I added the various resurces to ensure localized user experience.
Use the App_GlobalResources deployment and add Resources to the Control Declaration
public interface IBaseFieldControl
{
string Title { get; set; }
string Description { get; set; }
string DescriptionCssClass { get; set; }
string RequiredText { get; set; }
string RequiredTextCssClass { get; set; }
bool HideTitle { get; set; }
void RenderFieldForCustomInput(HtmlTextWriter output);
}
The RenderFieldForCustomInput is just a wrapper for RenderFieldForInput which unfortionatly is protected!{
string Title { get; set; }
string Description { get; set; }
string DescriptionCssClass { get; set; }
string RequiredText { get; set; }
string RequiredTextCssClass { get; set; }
bool HideTitle { get; set; }
void RenderFieldForCustomInput(HtmlTextWriter output);
}
I Also creatd a RenderCustom Extention method to render the label ++
public static class BaseFieldControlExtentions
{
public static void RenderCustom(this BaseFieldControl field, HtmlTextWriter output)
{
var iField = field as IBaseFieldControl;
if (iField == null)
throw new ArgumentException("control must implement IBaseFieldControl", "field");
output.Write("<div align=\"left\" class=\"ms-formfieldcontainer\" >");
var container = GetDivControl("ms-formfieldlabelcontainer");
container.Attributes.Add("nowrap", "nowrap");
var labelText = GetSpanControl("ms-formfieldlabel", string.IsNullOrEmpty(iField.Title) ? field.Field.TitleResource.GetValueForUICulture(field.Web.Locale) : iField.Title);
labelText.Attributes.Add("nowrap", "nowrap");
container.Controls.Add(labelText);
var lableRequired = GetSpanControl(iField.RequiredTextCssClass, iField.RequiredText);
container.Controls.Add(lableRequired);
var labelDecription = GetSpanControl(iField.DescriptionCssClass, iField.Description);
container.Controls.Add(labelDecription);
container.RenderControl(output);
output.WriteLine("<div class=\"ms-formfieldvaluecontainer\" >");
output.WriteLine("<span dir=\"none\" >");
iField.RenderFieldForCustomInput(output);
output.WriteLine("</span>");
output.WriteLine("</div>");
output.WriteLine("</div>");
}
private enum HtmlContolType
{
div, span
}
private static HtmlGenericControl GetControl(HtmlContolType contolType, string className)
{
var ctrl = new HtmlGenericControl(contolType.ToString());
ctrl.Attributes.Add("class", className);
return ctrl;
}
private static HtmlGenericControl GetDivControl(string className)
{
return GetControl(HtmlContolType.div, className);
}
private static HtmlGenericControl GetSpanControl(string className)
{
return GetControl(HtmlContolType.span, className);
}
private static HtmlGenericControl GetSpanControl(string className, string innerText)
{
var ctrl = GetSpanControl(className);
ctrl.InnerText = innerText;
return ctrl;
}
}
{
public static void RenderCustom(this BaseFieldControl field, HtmlTextWriter output)
{
var iField = field as IBaseFieldControl;
if (iField == null)
throw new ArgumentException("control must implement IBaseFieldControl", "field");
output.Write("<div align=\"left\" class=\"ms-formfieldcontainer\" >");
var container = GetDivControl("ms-formfieldlabelcontainer");
container.Attributes.Add("nowrap", "nowrap");
var labelText = GetSpanControl("ms-formfieldlabel", string.IsNullOrEmpty(iField.Title) ? field.Field.TitleResource.GetValueForUICulture(field.Web.Locale) : iField.Title);
labelText.Attributes.Add("nowrap", "nowrap");
container.Controls.Add(labelText);
var lableRequired = GetSpanControl(iField.RequiredTextCssClass, iField.RequiredText);
container.Controls.Add(lableRequired);
var labelDecription = GetSpanControl(iField.DescriptionCssClass, iField.Description);
container.Controls.Add(labelDecription);
container.RenderControl(output);
output.WriteLine("<div class=\"ms-formfieldvaluecontainer\" >");
output.WriteLine("<span dir=\"none\" >");
iField.RenderFieldForCustomInput(output);
output.WriteLine("</span>");
output.WriteLine("</div>");
output.WriteLine("</div>");
}
private enum HtmlContolType
{
div, span
}
private static HtmlGenericControl GetControl(HtmlContolType contolType, string className)
{
var ctrl = new HtmlGenericControl(contolType.ToString());
ctrl.Attributes.Add("class", className);
return ctrl;
}
private static HtmlGenericControl GetDivControl(string className)
{
return GetControl(HtmlContolType.div, className);
}
private static HtmlGenericControl GetSpanControl(string className)
{
return GetControl(HtmlContolType.span, className);
}
private static HtmlGenericControl GetSpanControl(string className, string innerText)
{
var ctrl = GetSpanControl(className);
ctrl.InnerText = innerText;
return ctrl;
}
}
Now I thought I was good to go, but i spoke too soon... My customer wanted the same feature for the Taxonomy control. Great another inherit... Well, this time Microsoft was so nice that they planned for this crazy requirement. The made the TaxonomyFieldControl sealed. Using Reflector and som guess I wrapped the field using the same IBaseFieldControl interface. Whola! A fully working Taxonomy Field...
public class TaxonomyFieldControl : BaseFieldControl, IBaseFieldControl
{
private BaseFieldControl _wrappedFieldControl;
public bool HideTitle { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DescriptionCssClass { get; set; }
public string RequiredText { get; set; }
public string RequiredTextCssClass { get; set; }
public void RenderFieldForCustomInput(HtmlTextWriter output)
{
RenderFieldForInput(output);
}
#region Public Override
public override object Value
{
get { return _wrappedFieldControl.Value; }
set { _wrappedFieldControl.Value = value; }
}
public override void Validate()
{
_wrappedFieldControl.Validate();
}
public override void UpdateFieldValueInItem()
{
_wrappedFieldControl.UpdateFieldValueInItem();
}
#endregion
#region Protected Override
protected override void RenderFieldForDisplay(HtmlTextWriter output)
{
var renderFieldForDisplay = _wrappedFieldControl.GetType().GetMethod("RenderFieldForDisplay", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
renderFieldForDisplay.Invoke(_wrappedFieldControl, new object[] { output });
}
protected override void OnInit(System.EventArgs e)
{
var ctrl = new Microsoft.SharePoint.Taxonomy.TaxonomyFieldControl { FieldName = FieldName };
_wrappedFieldControl = ctrl;
Controls.Add(ctrl);
base.OnInit(e);
}
protected override void RenderFieldForInput(HtmlTextWriter output)
{
var renderFieldForInput = _wrappedFieldControl.GetType().GetMethod("RenderFieldForInput", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
renderFieldForInput.Invoke(_wrappedFieldControl, new object[] { output });
}
protected override void Render(HtmlTextWriter output)
{
this.RenderCustom(output);
}
#endregion
}
{
private BaseFieldControl _wrappedFieldControl;
public bool HideTitle { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string DescriptionCssClass { get; set; }
public string RequiredText { get; set; }
public string RequiredTextCssClass { get; set; }
public void RenderFieldForCustomInput(HtmlTextWriter output)
{
RenderFieldForInput(output);
}
#region Public Override
public override object Value
{
get { return _wrappedFieldControl.Value; }
set { _wrappedFieldControl.Value = value; }
}
public override void Validate()
{
_wrappedFieldControl.Validate();
}
public override void UpdateFieldValueInItem()
{
_wrappedFieldControl.UpdateFieldValueInItem();
}
#endregion
#region Protected Override
protected override void RenderFieldForDisplay(HtmlTextWriter output)
{
var renderFieldForDisplay = _wrappedFieldControl.GetType().GetMethod("RenderFieldForDisplay", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
renderFieldForDisplay.Invoke(_wrappedFieldControl, new object[] { output });
}
protected override void OnInit(System.EventArgs e)
{
var ctrl = new Microsoft.SharePoint.Taxonomy.TaxonomyFieldControl { FieldName = FieldName };
_wrappedFieldControl = ctrl;
Controls.Add(ctrl);
base.OnInit(e);
}
protected override void RenderFieldForInput(HtmlTextWriter output)
{
var renderFieldForInput = _wrappedFieldControl.GetType().GetMethod("RenderFieldForInput", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
renderFieldForInput.Invoke(_wrappedFieldControl, new object[] { output });
}
protected override void Render(HtmlTextWriter output)
{
this.RenderCustom(output);
}
#endregion
}
At the end I added the various resurces to ensure localized user experience.
Use the App_GlobalResources deployment and add Resources to the Control Declaration
<webcontrols:textfield description="<%$Resources:layout, field_Title_desc %>" descriptioncssclass="edit-mode-field-description" fieldname="PublishingContact" id="eTextFieldTitle" runat="server" HideTitle="False" Title="" RequiredText="<%$Resources:layout, field_required_text %>" RequiredTextCssClass="edit-mode-required-field-marker" />



Ingen kommentarer:
Legg inn en kommentar