SharePoint Custom Field(Button)

안녕하세요?
오늘은 저번에 공지한대로 커스텀 텍스트 필드에 버튼 컨트롤을 넣어서 작업을 해보겠습니다.

우선 이번에는 저번과 다르게 디폴트 템플릿도 만들 것이고 display할 때 기본 컨트롤 뿐만 아니라.

버튼이 함께 들어 가도록 하겠습니다.

1. class를 생성 하고 SPField를 상속을 받도록 하겠습니다.

2. 그냥 빌드를 하면은 저번과 같이 에러가 나게 됩니다. 생성자를 넣지 않아서 나는오류입니다.
   그럼 저번과 같이 생성자 또한 정의를 해보겠습니다.

3. 그런 다음 FiellRenderingControl을 상속을 받고 제가 ��정한 class를 넣어 주도록 하겠습니다.

 4. 그리고 금방 생성한 class에 baseFieldControl을 상속 받도록 하겠습니다.

5. 그런 다음 아까 말했듯이 디폴트 템플릿을 사용자 지정으로 넣습니다.(아무 이름이나 상관 없음.)

6. ControlTemplate를 생성 합니다.(이름 상관 없음.)

7. ControlTemplate의 내용은 아래의 그림과 같이 정의를 해줍니다.(Source단 참조, Template안에 컨트롤 및 테그 아무렇게 넣어도됨.)
  * SharePoint:RenderingTemplate 의 ID는 디폴트 템플릿의 사용자 이름으로 해야됨.(아래 그림 참조)

8. 컨트롤을 정의 하겠습니다 Template에 있는 텍스트 박스 하나, Display에 뿌릴 테이블 하나, 버튼 등록을 위한 버튼 하나.

9. 텍스트박스를 넣기 쉽게 하기 위해서 캡슐화 하겠습니다.

10. 값을 저장 하고 빼오기 위해서 Value를 상속 받고 Text의 값의로 설정 하도록 하겠습니다.

 

11. 그리고 버튼을 클릭 이벤트를 생성 하도록 하겠습니다.


 
12. 이제 Display시 뿌려질 내용을 하나의 함수를 생성 해서 넣도록 하겠습니다. (Microsoft.SharePoint.WebControls.OWSForm이라는 것을 참조)

13. 해당 페이지에 뿌려줄때 동작 하는 CreateChildControls를 상속 받는다 (필드가 널인지 체크, base컨트롤 생성 및 display모드시 버튼 등록, New모드시 기본값설정)

14. SharePoint에서 Display이시 컨트롤을 랜더링을 관장하는 RenderFieldForDisplay를 상속 받는다.(아까 생성한 Table을 뿌림.)

 

15. 이벤트에 해당 컬럼의 값을 +1 시킨다.

 

16. 필드 타입 정의 XML (저번 XML그대루 같다가 씁니다;; 편집해서 쓰세요~)

17. 해당 dll은 객에 등록, Controltemplate랑 xml은 Controltemplates랑 xml폴에 각각 복사 후 iisreset

완료 화면 1)

완료 2)

 

완료 3)

 

완료 4)

 

 

완료 6)

소스 1)

[code:html;In=on] 

    public class CustomButton : Microsoft.SharePoint.SPField
    {
        public CustomButton(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
        {
        }//

        public CustomButton(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName, displayName)
        {
        }//

        public override BaseFieldControl FieldRenderingControl
        {
            get
            {
                BaseFieldControl bfc = new CustomButtonBaseControl();
                bfc.FieldName = InternalName;
                return bfc;
            }
        }//FieldRenderingControl

    }//class

[/code]

소스 2)

 [code:html;In=on]

    public class CustomButtonBaseControl : BaseFieldControl
    {

        protected TextBox Ctb_txt;
        public Button spnote_btn;
        private Table table;

        protected override string DefaultTemplateName
        {
            get
            {
                return "btn_SPNote_Template";
            }
        }//DefaultTemplateName

        protected override void CreateChildControls()
        {
            if (base.Field == null)
            {
                return;
            }

            base.CreateChildControls();
           
            if (base.ControlMode == SPControlMode.Display)
            {
                spnote_btn = new Button();
                spnote_btn.Click += new EventHandler(spnote_btn_Click);
                spnote_btn.ID = "spnote_btn";
                spnote_btn.Text = "버튼테스트";
                DisPalyFormAdd();
            }
            else
            {
                Ctb_txt = (TextBox)this.TemplateContainer.FindControl("SPNote_txt");
                Ctb_txt.Enabled = false;
                if (base.ControlMode == SPControlMode.New)
                {
                    Ctb_txt.Text = "0";
                }
            }

        }//CreateChildControls

        public void DisPalyFormAdd()
        {
            Microsoft.SharePoint.WebControls.OWSForm form =
                new Microsoft.SharePoint.WebControls.OWSForm();
            Controls.Add(form);
            table = new Table();
            form.Controls.Add(table);
            table.Width = Unit.Percentage(80);
            TableRow row = new TableRow();
            table.Rows.Add(row);
            row.BackColor = Color.White;
            TableCell cell = new TableCell();
            cell.Width = Unit.Pixel(150);
            cell.Attributes["class"] = "ms-vb2";
            cell.Controls.Add(spnote_btn);
            row.Cells.Add(cell);
               
        }//DisPlayFormAdd

        protected override void RenderFieldForDisplay(HtmlTextWriter output)
        {
            base.RenderFieldForDisplay(output);
            if (table == null)
            {
                DisPalyFormAdd();
            }

            table.RenderControl(output);

        }//RenderFieldForDisplay

        void spnote_btn_Click(object sender, EventArgs e)
        {
            Web.AllowUnsafeUpdates = true;
            String itemvalue =  this.ItemFieldValue.ToString();
            this.ItemFieldValue = (int.Parse(itemvalue) + 1).ToString();
            this.Item.Update();
            Web.AllowUnsafeUpdates = false;
            string responseurl= this.Page.Request.Url.ToString();
            this.Page.Response.Redirect(responseurl);
           
        }//spnote_btn_Click

        public virtual string Text
        {
            get
            {
                this.EnsureChildControls();
                if (this.Ctb_txt == null)
                {
                    return null;
                }
                return this.Ctb_txt.Text;
            }
            set
            {
                this.EnsureChildControls();
                if (this.Ctb_txt != null)
                {
                    this.Ctb_txt.Text = value;
                }
            }
        }//Text

        public override object Value
        {
            get
            {
                return this.Text;
            }
            set
            {
                if (base.Field != null)
                {
                    this.Text = base.Field.GetFieldValueForEdit(value);
                }
            }
        }//Value

    }//class

[/code] 소스 3)

[code:html;In=on]

<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
  <FieldType>
  <Field Name="TypeName">사용자정의버튼</Field>
  <Field Name="ParentType">Text</Field>
  <Field Name="TypeDisplayName">사용자정의버튼</Field>
  <Field Name="TypeShortDescription">사용자정의버튼</Field>
  <Field Name="UserCreatable">TRUE</Field>
  <Field Name="FieldTypeClass">SPnote.SharePoint.SPField.SPFeildText.CustomButton, SPnote.SharePoint.SPField, Version=1.0.0.0, Culture=neutral, PublicKeyToken=be2c734ef24c0327</Field>
  <RenderPattern Name="DisplayPattern">
   <Column HTMLEncode="TRUE" AutoHyperLink="TRUE" AutoNewLine="TRUE"/>
  </RenderPattern>
 </FieldType>
</FieldTypes>

[/code]

SharePoint Custom Field

SPFieldText 를 상속을 하여서 간단히 필드를 하나 만들어 보겠습니다.

 

SPFieldTextSharePoint에서 기본적으로 텍스트 박스 형태의 255길이의 문자를 쓸 수 있는 텍스트 박스 입니다.

 

우선 CS단을 만들고 해당 SPFieldText 를 상속 해 보겠습니다.

  

그리고 빌드를 하면은 에러가 나게 되어있습니다.

베이스 컨트롤의 생성자 들을 안 넣었기 때문입니다. 

 

이런 식으로 넣어 주면은 에러 없이 돌아 갑니다.

 

다음으로 해당 컨트롤에 필드랜더링컨트롤을 오버라이드 해서 상속을 받아서 커스텀

된 해당 필드를 넣어 보도록 하겠습니다.

 

우선 컨트롤을 오버라이드를 하고,

클래스를 하나 만들어서 아래와 같이 소스를 채워 넣습니다.

그 다음 금방 만든 class파일에 가서 basefieldcontrol을 상속 해서 만들어 둡니다.

 

 

텍스트 박스를 바꿔야 하기 때문에 우선 텍스트 박스를 상속하겠다고 선언 하고, 그리고 기본 템플릿을

 SharePoint FieldText 가 사용 하는 “TextField”라는 템플릿을 사용 하도록 하겠습니다.

 

우선 값을 넣을 수 있는 Text라는 인자 값을 리펙터링으로 선언 해서 텍스트박스 값을 집어 넣습니다.

 

 

그리고 value를 오버라이드 해서 해당 값을 채워 줍니다.

 

 

그리고 나서 CreateChildControls를 오버라이드 해서 해당 컨트롤에 뿌려 질 때 할 행동들을 집어 넣을

수 있습니다. (편집과 새로 만들기 시 값을 넣어줘야 함.)

Findcontrol로 해당 필드를 찾아서 넣어 주면은 랜더링이 끝나고 나서 값을 채울 때 해당 필드가 널 값이

 아니기 때문에 값을 넣게 됨( 참고 : 해당 필드 값은 DefaultTemplates.ascx에 정의 되어있음. )

* 기본템플릿에서 TextField로 정의 되어있으니 DefaultTemplates.ascx파일에서 검색을 하시면은 한결 이해가 쉽습니다.

 

  

key파일을 생성 하고 빌드 한 다음 객에 등록을 합니다.

 

 

그리고 xml파일을 하나 만들어서 해당 내용을 집어 넣습니다.

(xml이름은 : fldtypes_아무이름  ß이런 식으로 맞춰주어야지 moss에서 인식을 합니다.)

FieldTypeClass 에 해당 파일의 dll정보 와 해당 class명을 넣어 주고 나서 12 폴더 밑에 xml파일에 넣어 주고 iis reset하면은 끝)

 

 

 

완료1)

완료2)

 

완료3)

 

소스1)

[code:html;In=on]

public class CustomTextField : SPFieldText
{
        public CustomTextField(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
        {
        }

        public CustomTextField(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName,displayName)
        {
        }

        public override BaseFieldControl FieldRenderingControl
        {
            get
            {
                BaseFieldControl cbc = new CustomTextBaseControl();
                cbc.FieldName = InternalName;
                return cbc;
            }
        }//FieldRenderingControl

}//class
[/code]

소스 2)

[code:html;In=on]

public class CustomTextBaseControl : BaseFieldControl
{
        protected TextBox customTextField;
       
        protected override string DefaultTemplateName
        {
            get
            {
                return "TextField";
            }
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            if ((base.ControlMode != SPControlMode.Display) && (base.Field != null))
            {
                this.customTextField = (TextBox)this.TemplateContainer.FindControl("TextField");
            }

        }

        public virtual string Text
        {
            get
            {
                this.EnsureChildControls();
                if (this.customTextField == null)
                {
                    return null;
                }
                return this.customTextField.Text;
            }
            set
            {
                this.EnsureChildControls();
                if (this.customTextField != null)
                {
                    this.customTextField.Text = value;
                }
            }
        }

 

        public override object Value
        {
            get
            {
                return this.Text;
            }
            set
            {
                if (base.Field != null)
                {
                    this.Text = base.Field.GetFieldValueForEdit(value);
                }
            }
        }

}
[/code]

소스 3)

[code:xml;In=on]

<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
 <FieldType>
  <Field Name="TypeName">사용자변경</Field>
  <Field Name="ParentType">Text</Field>
  <Field Name="TypeDisplayName">사용자변경텍스트</Field>
  <Field Name="TypeShortDescription">사용자변경텍스트</Field>
  <Field Name="UserCreatable">TRUE</Field>
  <Field Name="FieldTypeClass">SPnote.SharePoint.SPField.SPFeildText.CustomTextField, SPnote.SharePoint.SPField, Version=1.0.0.0, Culture=neutral, PublicKeyToken=be2c734ef24c0327</Field>
  <RenderPattern Name="DisplayPattern">
   <Column HTMLEncode="TRUE" AutoHyperLink="TRUE" AutoNewLine="TRUE"/>
  </RenderPattern>
 </FieldType>
</FieldTypes> 

[/code] 

이상으로 커스텀 필드에 대해서 마쳤습니다. 내용이 많이 부족 하지만 부족한 내용들은 개인들이 

채워 주시면은 고맙겠습니다.

다음에는 버튼 필드를 만들어 보도록 하겠습니다.                   

 

 

 

 

 

Popup Description balloon for Calendar Items

Calendar List can be used to share information about events, appointments, meetings and etc.


While I was using this list, I found that it will be better to popup its Description value when a user mouse over to each item cause it basically doesn't. Here's what the common columns of Calendar List are.

Column Name Description
Title (required) Single line of text
Location Single line of text
Start Time (required) Date and time
End Time (required) Date and time
Description Multiple lines of text


Unfortunately, Description column type is "Multiple lines of text" which means this column contains HTML tags that this have to be processed to remove HTML tags before showing its value. Here is a Display Item image and a raw value of Description column. 


  # Display Item

ex) Raw? Description Value
[code:html;ln=off]

<div>OCS R2 Verification Call for VSP</div>
<div>I support OC engineers to get it done successfully!</div>
<div>&nbsp;</div>
<div>Bold:<strong>&nbsp;Bold</strong> </div>
<div><font color="#ff9900"><font color="#000000">Font Color:</font> Orange</font></div>

[/code]


So, I need to remove HTML tags and I used Regular Expression.
ex) System.Text.RegularExpressions.Regex.Replace(Description Column Value, "<[^>]*>", string.Empty)


But where should I edit for this??? The answer is DefaultTemplates.ascx under
12 Hive\TEMPLATE\CONTROLTEMPLATES\... You can change this directly or override into new one. Calendar List has 3 ways "Day", "Week", "Month" to show Items and you need to change three Templates and they are.

  1. 2477: CalendarViewMonthItemTemplate
  2. 2539: CalendarViewDayItemTemplate
  3. 2617: CalendarViewWeekItemTemplate

    [Line Number: Template Name]


It is time to edit this template. Find A tag and put the title attribute with this codes and execute IISRESET.

[code:html;ln=off]

title="<%# System.Text.RegularExpressions.Regex.Replace(DataBinder.Eval(Container,"DataItem.Description",""), "<[^>]*>", string.Empty)%>"

[/code]


Now you can see the poping up Description value if you mouse over to any item that has Description value.



  # Demo poping up Description value

Custom Resource Provider for SharePoint Localization

 At first, I simply implemented 1. Custom Resource Provider which reads browser preference only but tricky customers wanted 2. Toggle Languages function. I used Cookie and Database for each user's localization data store and I described here how it's implemented.

* Click images below to see larger ones. 
 

1. Custom Resource Provder


2. SharePoint Localization to support a toggle function for two languages

Localization and Theme

1. SharePoint Localization and Limitation
What I have been exprienced on SharePoint Localizations are not practical for non-English users such as Variations and Team Sites. In my case, Korean customers want languages to be changed for their applications when they click buttons or by user's browser preference not like SharePoint Team Sites. As you might have noticed, replacing the asp menu to a custom one make them lose its original functions. Anyways they know this and liked it. I think adding a new layer that supports localization for asp menu is a better idea.

2. Custom Resource Provider
I have developed a custom resource provider and this supports browsers preference and toggling languages. To implement the function "Toggle Languages", I use Cookie and Database to save and retrieve user's language value.

3. SharePoint Theme
SharePoint Theme can be changed at  Home > Site Settings > Site Theme (_layouts/themeweb.aspx) but it affects all users.

4. Custom Control for user Theme enabled
Unfortunately, tricky Korean customers want individual themes such as clicking color buttons changes from current to new one and this doesn't affect other users. I created a Control to render custom css link for each user.


Here are sample images and click each image to see larger ones.
(Only menus are shown. Refer to the last image to see Page localzation)

 

SharePoint Page Localization
  # Localization Example ( can be toggled between English and Korean ) 

 


  # Individual Theme Demo