Getting values of internal properties in SharePoint 2007

, , , ,

SharePoint has a lot of gold under the hood. Unfortunately for us – developers not all of it is publicly available. Some methods/properties are marked as internal what makes it impossible for us to use is custom functionality we’re developing. But do you really develop your own alternatives or is there a way to get to those gems after all?

GroupedItemPicker – almost unusable?

Grouped Item Picker SharePoint control

One of the examples of the situation I’ve described above is the GroupedItemPicker- a list control which allows the end users to select multiple items. Comparing to the standard list box the GroupedItemPicker provides a richer experience and makes selecting multiple items way easier.

By default a multiple lookup field stores the selected items as ID1;#Title1;#ID2;Title2 string. Unfortunately, there is a problem when querying the content of a MultiLookup field. At the end of the day, you might to create an alternative field type which would correctly support selecting multiple values and making the value available to a query.

No matter how you would solve the plumbing the odds are high that you would query the value as text which would resemble the standard MultiLookup value (ID1;#Title1;#ID2Title2). There is one problem however…

I assume you would use GroupedItemPicker to provide the same great experience as the standard MultiLookup SharePoint field. The problem is that GroupedItemPicker provides you access to the selected ID’s (GroupedItemPicker.SelectedIds) only. The selected text (GroupedItemPicker.SelectedTokens) is accessible internally only! Does it mean that you must create your own control which would work exactly the same as the GroupedItemPicker? Luckily not!

Reflecting the GroupedItemPicker

It turns out that you can still get to the values of internal properties using reflection. And the best of it all: it’s not even that complicated! Take a look at the following method I’ve made which simplifies getting type safe value of any property:

public static bool TryGetPropertyValue<TValue>(object o, string propertyName, out TValue value)
{
  bool succes = false;
  value = default(TValue);
  foreach (PropertyInfo pi in o.GetType().GetProperties(BindingFlags.Default | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
  {
    if (pi.Name.Equals(propertyName) && pi.CanRead)
    {
      object rawValue = pi.GetValue(o, null);
      if (rawValue is TValue)
      {
        value = (TValue)rawValue;
        succes = true;
      }
    }
  }
  return succes;
}

Now if you want to retrieve the value of a non-public property you can do it like this:

InternalClass ic = new InternalClass();
int value = 0;
if (TryGetPropertyValue<int>(ic, "InternalProperty", out value))
{
    // do something
}

As far as I’m concerned it’s a lot less development than creating a fully functional control similar to GroupedItemPicker.

GroupedItemPicker is not the only gem stored in SharePoint. There is a lot more of them. Having the TryGetPropertyValue in your utils can enable to benefit even more of the SharePoint framework.


Possibly related posts

16 Responses to “Getting values of internal properties in SharePoint 2007”

  1. Amy Says:

    Hi there,

    Thank you for your post. I am trying to create a custom field using the GroupPickerControl. However, I am having a little bit of trouble configuring the control. Would you be able to provide a small sample of how to set the GroupPickerControl properties?

    Thanks,
    Amy

  2. Waldek Mastykarz Says:

    Could you provide any more information on the challenges you're facing?

  3. Amy Says:

    Hi,

    Thanks for the quick reply. I am having difficulty setting the properties of the GroupedItemPicker control itself. It seems as though I am not setting all of the required properties (or I am setting them incorrectly) because when I get to the PreRender event in the custom field I get the 'object reference not set to an instance of an object' error. I think I am setting the control up incorrectly in the ascx file that I am using for the RenderingTemplate for my custom field. The problem is that I can't find much documentation on how to use the control. Would you be able to help me by providing an example of how this control could be set up?

  4. Waldek Mastykarz Says:

    Have you tried moving the setup code to the OnLoad event? Could you provide some more info on the error you're getting, ie. which properties are you setting, etc?

  5. Amy Says:

    Hi there,

    My apologies for not supplying enough info…

    No, I have not tried moving the setup code to the OnLoad event. I will try that…

    This is how I am trying to use the GroupedItemPicker control in the ascx file:

    <SharePoint:RenderingTemplate ID="CascadingGroupPickerFieldControl" runat="server">
    <Template>
    <SharePoint:GroupedItemPicker ID="GroupedItemPickerControl" runat="server"
    CandidateControlId="AvailableItems"
    ResultControlId="SelectedItems"
    AddButtonId="AddButton"
    RemoveButtonId="RemoveButton">
    <table class="ms-long" cellpadding="0" cellspacing="0" border="0">
    <tr>
    <td class="ms-input">
    <div style="width:190px;height:126px;overflow:scroll">
    <select
    id="AvailableItems"
    name="AvailableItems"
    multiple="multiple">
    </select>
    </div>
    </td>
    <td style="padding-left:10px">
    <td align="center" valign="middle" class="ms-input">
    <button id="AddButton">>></button>
    <br />
    <button id="RemoveButton"><<</button>
    </td>
    <td style="padding-left:10px">
    <td class="ms-input">
    <div style="width:190px;height:126px;overflow:scroll">
    <select
    id="SelectedItems"
    name="SelectedItems"
    multiple="multiple">
    </select>
    </div>
    </td>
    </tr>
    </table>
    </SharePoint:GroupedItemPicker>
    </Template>
    </SharePoint:RenderingTemplate>

    The complete error I am getting is:
    [NullReferenceException: Object reference not set to an instance of an object.]
    Microsoft.SharePoint.WebControls.GroupedItemPicker.OnPreRender(EventArgs e) +1020
    System.Web.UI.Control.PreRenderRecursiveInternal() +86
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.WebControls.WebParts.WebPart.PreRenderRecursiveInternal() +62
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Control.PreRenderRecursiveInternal() +170
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2041

    Am I using the control correctly?
    Thanks for your help :)

  6. Waldek Mastykarz Says:

    @Amy: I've been using the GroupedItemPicker programmatically so I don't have any markup example I could compare it to. Have you tried looking inside the Application Pages provided in SharePoint to find an example of how they define it in markup?

  7. Amy Says:

    Yes I have had a quick look, but no luck… I will look again to make sure. Quick question… what properties of the GroupedItemPicker have you been setting programmatically?

  8. Waldek Mastykarz Says:

    @Amy: I use it as a Control for my custom field type. The only property I set is the FieldName to bind the control to the field. In the custom control I've made I override the DefaultTemplateName property and return "MultipleLookupField" as value.

  9. Amy Says:

    Hi Waldek,

    I am also trying to use the GroupedItemPicker as a control in a custom field type… I return SPFieldMultiChoiceValue as the field value. When I override the DefaultTemplateName I return the RenderingTemplate ID in the ascx file that I created… That\'s where I\'m running into problems… Is it possible to send me an example of how you use it programmatically in your custom field type?

  10. John Berlo Says:

    I too am trying to use this like Amy. I'm defining it within a control that I'm embedding into a web part. Also, like Amy, I'm getting the same error. A sample of how you use this within code would be wonderful!

    Thanks,
    —John

  11. Amy Says:

    @John – I\\\'m not sure if this helps, but you can find an example of how the GroupedItemPicker control is used in the LAYOUTS directory in the AddContentTypeToList.aspx page. The markup in the page might give you a clue as to what properties you need to set programmatically.

    Amy

  12. andy Says:

    @Amy & John. Your getting the "object reference not set to an instance of an object" because you need to create at least 4 additional controls besides the groupedItemPicker. These need to be two container controls where the picker should store its candidate items and selected items and 2 buttons (add and remove) that will move the items between these 2 containers. So basically besides the picker you'll have to create 2 SPHtmlSelect controls and 2 HtmlInputButton controls. Then set the CandidataControlId, ResultControlId, AddButtonId, RemoveButtonId properties of the picker to point to these.
    PS: Like Amy said you can also check the .ascx file to see how the picker control is configured. (you'll notice the above there also).

  13. vejay Says:

    Hi,
    I am using the "GroupedItemPicker" in one of my custom field controls and what I need is the items in the control be sorted by the Created Date. I was able to get the source which is sorted and have added the items. Once the field is rendered the items loose the sort order and are ordered by alphabet is it the default behaviour of the control or am i missing some this here

    Thanks

  14. Waldek Mastykarz Says:

    @vejay: If you're sure that your data source is sorted then it must be the GroupedItemPicker that resets sorting. I'm not sure if there is a way to avoid it.

  15. ray Says:

    I\'am using a GroupedItemPicker in a Web Part, so i\'am creating the childs control programmatically. I need to know how set the properties of GroupedItemPicker. Here is my code:

    public class StudentsPicker : System.Web.UI.WebControls.WebParts.WebPart
    {
    GroupedItemPicker picker;
    SPHtmlSelect students, addedStudents;
    Button btt_add, btt_remove;
    DropDownList select_groups;

    public WebooStudentsPicker()
    {
    }

    protected override void CreateChildControls()
    {
    //
    students = new SPHtmlSelect();
    students.ID = \"students\";
    students.Multiple = true;
    Controls.Add(students);

    addedStudents = new SPHtmlSelect();
    addedStudents.ID = \"addedStudents\";
    addedStudents.Multiple = true;
    Controls.Add(students);

    select_groups = new DropDownList();
    select_groups.ID = \"selectGroups\";
    Controls.Add(select_groups);

    btt_add = new Button();
    btt_add.ID = \"bttAdd\";
    Controls.Add(btt_add);

    btt_remove = new Button();
    btt_remove.ID = \"bttRemove\";
    Controls.Add(btt_remove);

    picker = new GroupedItemPicker();
    picker.AddButtonId = btt_add.ID;
    picker.RemoveButtonId = btt_remove.ID;
    picker.ResultControlId = addedStudents.ID;
    picker.GroupControlId = select_groups.ID;
    picker.CandidateControlId = select_groups.ID;

    picker.Clear();
    picker.AddItem(\"ID\", \"Adams Item\", \" Adams Description\", \" Adams Group\");
    Controls.Add(picker);
    base.CreateChildControls();
    }
    }

    Could you tell me what is wrong ?

  16. Raimil Says:

    I have a solution. To see GroupedItemPicker used inside a web part follow this link:
    http://www.weboomania.com/index.php/2009/12/14/usando-el-groupeditempicker-de-sharepoint/

    Here I configured the control GroupedItemPicker
    regardless
    raimil

Leave a Reply

Security Code:

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS
Copyright © 2007 - 2012 Waldek Mastykarz

Creative Commons License