Friday, October 19, 2007

Customizing EntityEditorWithPicker

Everyone, who use Sharepoint had seen PeopleEditor control. It very useful in many cases - for example in permission forms:
PeopleEditor

 

But this control can be used not only for looking for users or groups. You can use its base class EntityEditorWithPicker and extend it to search any data. I will show you very simple example how to do this.

We should extend three classes:

using System; 
using System.Collections.Generic; 
using System.Text; 
using Microsoft.SharePoint.WebControls; 

namespace EntityEditorTest 
{ 
  public class CustomEntityEditor : EntityEditorWithPicker 
  { 
    protected override void OnInit(EventArgs e) 
    { 
      base.OnInit(e); 
      PickerDialogType = typeof (CustomPickerDialog); 
    } 

    public override PickerEntity ValidateEntity(PickerEntity needsValidation) 
    { 
      if (needsValidation.Key.Equals("igor", StringComparison.InvariantCultureIgnoreCase)) 
      { 
        needsValidation.DisplayText = "Igor Kozlov"; 
        needsValidation.IsResolved = true; 
      } 
      return needsValidation; 
    } 
  } 
}
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.WebControls;

namespace EntityEditorTest
{
  public class CustomPickerDialog : PickerDialog
  {
    public CustomPickerDialog()
      : base(new CustomQueryControl(), new TableResultControl(), new CustomEntityEditor())
    {
      ArrayList columnDisplayNames = ((TableResultControl)base.ResultControl).ColumnDisplayNames;
      columnDisplayNames.Clear();
      columnDisplayNames.Add("Name");
      columnDisplayNames.Add("Description");
      ArrayList columnNames = ((TableResultControl)base.ResultControl).ColumnNames;
      columnNames.Clear();
      columnNames.Add("Name");
      columnNames.Add("Description");
      ArrayList columnWidths = ((TableResultControl)base.ResultControl).ColumnWidths;
      columnWidths.Clear();
      columnWidths.Add("30%");
      columnWidths.Add("70%");
    }

  }
}
 
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Microsoft.SharePoint.WebControls;

namespace EntityEditorTest
{
  public class CustomQueryControl : SimpleQueryControl
  {
    public CustomQueryControl()
    {
      Load += CustomQueryControl_Load;
    }

    void CustomQueryControl_Load(object sender, EventArgs e)
    {
      if (!Page.IsPostBack)
      {
        EnsureChildControls();
        mColumnList.Items.Add("Name");
        mColumnList.Items.Add("Description");
      }
    }

    protected override int IssueQuery(string search, string groupName, int pageIndex, int pageSize)
    {
      DataTable dummyTable = GetDummyTable();

      PickerDialog.Results = dummyTable;
      PickerDialog.ResultControl.PageSize = dummyTable.Rows.Count;

      return dummyTable.Rows.Count;
    }

    private DataTable GetDummyTable()
    {
      DataTable dummyTable = new DataTable();
      dummyTable.Columns.Add("Name");
      dummyTable.Columns.Add("Description");

      DataRow row1 = dummyTable.NewRow();
      row1["Name"] = "Name 1";
      row1["Description"] = "Description 1";
      dummyTable.Rows.Add(row1);

      DataRow row2 = dummyTable.NewRow();
      row2["Name"] = "Name 2";
      row2["Description"] = "Description 2";
      dummyTable.Rows.Add(row2);
      return dummyTable;
    }

    public override PickerEntity GetEntity(DataRow dr)
    {
      PickerEntity entity = new PickerEntity();
      entity.DisplayText = "" +dr["Name"];
      entity.Key = "" + dr["Name"];
      entity.Description = "" + dr["Description"];
      entity.IsResolved = true;
      return entity;
    }
  }
}

And there is result:

Custom Editor

30 comments:

J.P. said...

Great sample! Keep on the good work

Matt said...

Thanks for the example code. One question.... when I click on the browse button I get an error:

"Only PickerDialog types can be used with the dialog. The type should be configured as a safecontrol in this site."

Am I missing something? Thanks!

Igor Kozlov said...

Put refference to your class to <SafeControls> in web.config.

Chris said...

Great Post!
The select works find for me. But I couldn't find a way to assgin the selected value back to the picker when the picker is edited again.

I try to assign value to the ResolvedEntities properties in the SyncChanges method of parent EditorPart control, but it doesn't display the value in the picker.

Do you have any idea?
Thanks!

Igor Kozlov said...

Sorry, I haven't synchronize Entities with popup picker.

Matt said...

Hey Igor, got another question.... should the search functionality actually work with this example? I see in your screenshot that you've typed in "11" as your search parameter but your search results are still returning both rows. Any idea how to filter the results by the search string?

Igor Kozlov said...

No. In this example search is not implemented.

Look on this method:

protected override int IssueQuery(string search, string groupName, int pageIndex, int pageSize)
{
DataTable dummyTable = GetDummyTable();

PickerDialog.Results = dummyTable;
PickerDialog.ResultControl.PageSize = dummyTable.Rows.Count;

return dummyTable.Rows.Count;
}

here search parameter have no affect on PickerDialog.Results. So you should rewrite this method for your needs.

CSLA said...

Thank you -- it was a very useful post. But, one thing is that, for me, the "Add->" button and the textbox to the right of it is NOT visible. How do I make it visible?

CSLA said...

Thank you for the help, it was very useful.
But, how do I make the "Add->" button and the textbox to the right of this button visible?

Hrvoje said...

maybe you find this usefull...
http://hrvojekusanic.blog.com/

Hrvoje said...

maybe you find this usefull...
http://hrvojekusanic.blog.com/

drudolph1 said...

Igor,

Do you know what the groupName parameter to IssueQuery() is linked to? How can we use it?

Thanks!
Daryl

sam said...

how do i use this classes on to a page ? Can anyone provide the code of the page where the classes can be used?

Igor Kozlov said...

You should add this control to webpart.


public class CustomSelect : System.Web.UI.WebControls.WebParts.WebPart
{
public CustomSelect()
{
this.ExportMode = WebPartExportMode.All;
}

protected override void CreateChildControls()
{
base.CreateChildControls();

// TODO: add custom rendering code here.
CustomEntityEditor editor = new CustomEntityEditor();
this.Controls.Add(editor);
}
}

sam said...

Thank you so much Igor,

I have another question though. I'm not able to pass the search string and also get the result . How exactly do we carry this task ?

sam said...

And also could i know how to use it as a usercontrol or in a web page instead of making it a webpart

SSK said...

hi.. how do you assign values to the editorcontrol or Fetch the resolved entities?

Rhaegys said...

To assign values to the control use the property CommaSeparatedAccounts
To get the resolved entities use the property Entities (this is an array list of PickerEntity objects).

sam said...

Hi,

When you enter an entity value which does nto validate and and shows back on the textbox as no exact matched found when we click on the unmatched entity we see a dropdown or a menu list pop up...
How do we change the menu list to show enitities which are a possible match like the peoplepicker contro ???

Please suggest

Jan said...

Hi,
I added custom picker in my webpart as Igor wrote.

But I don't have icons for browse and check items (javascript runs OK). Must I set CheckButtonImageName and BrowseButtonImageName to something special? Where I have to give this pictures?

When I give custom picker to aspx page, it is good.

Jan said...

Hi,
OK, I found answer: I must set:
picker.BrowseButtonImageName = "/_layouts/images/addressbook.gif";

picker.CheckButtonImageName = "/_layouts/images/resolve.gif";


but now I have problem, when I add 2 pickers in webpart -
When I select value in first dialog window, value in first textbox is set (OK).
But when I select entity in second dialog window, first textbox is set to this value.

Can I use only 1 custom picker dialog in webpart?

Gitolekha said...

I have a tab control in which I have a peopleeditor in the first tab called "pplowner". The last tab is a summary of values of controls selected in the other tabs. I have to do this using javascript. currently, I am doing,

var elem = document.forms[0].elements;
for(var i=0; i < elem.length; i++)
{
if(elem[i].id.indexOf("pplOwner") != -1 && elem[i].id.indexOf("TextBox") != -1) users = elem[i].value;
}

Now, I display the value in users in a label.
The poblem that I am facing is,
if I delete a value from the peopleeditor's textbox, I still get the old values in users.
Also, the names are displayed as domain/userid, whereas I want it as user's name as it is shown in the peopleeditor.
Can you suggest a solution?

Srikanth said...

Hi Igor,

I'm having hard time to populate user name(resolved entity)value to PeoplEditor control. I'm using a custom edit form for MOSS List, which should pull the user name from the list and should show the same in the PeopleEditor control on the form. Can you please let me know how to acheive it ?

Julia Osipova said...

Hi, Igor.
I have a web part with several custom EntityEditorWithPicker controls. I need to get data from different tables and different databases, when a user click on Search button on the dialog picker. How can I create custom properties, such as database connection string and SqlQuery in my SimpleQueryControl class and how to populate them from the web part where I create my CustomEntityEditorWithPicker?

Thank you.

Rahul S. Gupta said...

Really, A good and Simple example for custom entity Editor.

!!!Great!!!

PrashanthSpark said...

Great Example for Peoplepicker!

Bu`i Va*n Nha^m Ty' said...

Hi!
Great Post!

I have a question, i don't want to use query, i want data load when the dialog show, how i can do that?
Thanks!

luckyzhu said...

A great gand brief example.
tiffany ring

Derek said...

Nice example. Any idea how to render an image in the picker results though?

Even though I have the required image tag html in the column, it shows as a string.

It seems to be rendered with the < > encoding by default.

Thanks!

Fernando Hunth said...

It'd be useful you upload a complete sample solution