How to implement IRuntimeFilter2 or how to target/filter web parts.

If you are looking at the various blog entries regarding IRuntimeFilter and are left wondering why it is considered a “deprecated” interface in SharePoint 2007 wonder no more! The functionality of IRuntimeFilter is not gone forever it has just been updated with newer functionality in IRuntimeFilter2. The primary functionality difference between the two interfaces is instead of implementing the filtering UI in a separate ASP.NET dialog you are now able to implement this directly in your very own web control.

This entry goes into detail on how to use this new interface. To save time I’ve borrowed the implementation of IRuntimeFilter created by Michael O’Donovan at https://blogs.msdn.com/modonovan/archive/2005/07/07/436394.aspx and updated it for IRuntimeFilter2.

The first major difference you’ll find between the two interfaces is with the InitializeStrings method. The original implementation defined the title, tooltip, button text and dialog sizing properties for a custom dialog you build and specify with the BuilderURL attribute in the <RuntimeFilter element of the web.config. (Note: The BuilderURL is no longer needed in implementations of IRuntimeFilter2)

IRuntimeFilter (Original)

public ArrayList InitializeStrings(CultureInfo cultureInfO)

{

 ArrayList strings = new ArrayList();

 strings.Add("Role Picker");

 strings.Add("Lets you pick which user roles can view this web part");

 strings.Add("Pick Role");

 strings.Add("dialogHeight:340px;dialogWidth:430px;help:no;status:no;resizable:no");

 return strings;

}

With IRuntimeFilter2 you only need to specify the title for your new web control.

IRuntimeFilter2

public ArrayList InitializeStrings(CultureInfo cultureInfO)

{

ArrayList strings = new ArrayList();

strings.Add("Choose Groups To Filter");

return strings;

}

 

 

The only new method in IRuntimeFilter2 is GetToolPaneControl(). This method is called by SharePoint to get an instance of the WebControl you are specifying for the user interface of the filter.

 

#region IRuntimeFilter2 Members

public IToolPaneControl GetToolPaneControl()

{

DevConWebControl.RFWebControl rfwc = new DevConWebControl.RFWebControl();

rfwc.ID = "ID_RDWebControl";

return rfwc;

}

#endregion

 

The implementation of RFWebControl is relatively straightforward. To keep things simple I’m only filtering on the current sites available groups but you can filter on anything.

 

    public class RFWebControl : WebControl, IToolPaneControl, INamingContainer, IPostBackDataHandler

    {

  // The listbox that holds the groups available for filtering

        ListBox lb;

       

        // Custom list entry so I know when the user wants to clear the filter

        const string CLEARVALUE = "Clear Filter";

 

        protected override void CreateChildControls()

        {

            base.CreateChildControls();

           

            lb = new ListBox();

            lb.ID = "ID_lbSelectedGroups";

            lb.SelectionMode = ListSelectionMode.Multiple;

 

            lb.Items.Add(CLEARVALUE);

            // Get the available groups available to filter on

            foreach (SPGroup spg in SPContext.Current.Web.Groups)

            {

                lb.Items.Add(spg.Name);

            }

            this.Controls.Add(lb);

 

 

            // Initialize listbox if there were groups previously selected

            if (Text.Length > 0)

            {

                String[] groups = Text.Split(new char[] { ',' });

                foreach (String g in groups)

                {

     foreach (ListItem li in lb.Items)

                    {

                        if (g.CompareTo(li.Text) == 0)

                            li.Selected = true;

                    }

                }

            }

        }

 

        protected override void OnPreRender(EventArgs e)

        {

            base.OnPreRender(e);

            // Register for postback so we can extract the selected

            // groups out in time to hand off to SharePoint

            this.Page.RegisterRequiresPostBack(this);

        }

 

        #region IToolPaneControl Members

        // This is our implementation of IToolPaneControl

        // SharePoint uses this value to persist the selected filter

        String _filterText = "";

        public string Text

        {

            get

            {

                return _filterText;

            }

            set

            {

                _filterText = value;

            }

        }

        #endregion

 

        #region IPostBackDataHandler Members

 

        bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)

        {

            String controlID = "ID_lbSelectedGroups";

            String fullID = "";

 

       // Loop through the controls until we find our listbox

            foreach (String k in postCollection.Keys)

            {

                if (k.Contains(controlID))

                    fullID = k;

            }

 

            if (postCollection[fullID] != null)

            {

                // This will contain the groups selected by the user

                // So we need to set the Text property with the filter

                Text = postCollection[fullID];

 

                // If the user selected clear empty the filter

                if (Text.CompareTo(CLEARVALUE) == 0)

                    Text = "";

            }

            return true;

        }

 

        void IPostBackDataHandler.RaisePostDataChangedEvent()

        {

        }

        #endregion

  }

 

The other major difference in the IRuntimeFilter2 implementation is since I’m filtering on groups stored in comma separated values my utility function CanUserSeePart() is different.

 

 

private bool CanUserSeePart(string groups)

{

        SPUser spu = SPContext.Current.Web.CurrentUser;

 

        String [] tmpGroups = groups.Split(new char[] { ',' });

 

        foreach (String g in tmpGroups)

        {

            foreach (SPGroup spg in spu.Groups)

                if (g.CompareTo(spg.Name) == 0)

         return true;

        }

        return false;

}

 

 

To try this sample out on your own download the project from the post attachment.Once the solution is built you will need to register both DevConRuntimeFilter.dll and DevConWebControl in the global assembly cache using gacutil –i DevConRuntimeFilter.dll and gacutil -i DevConWebControl.

 

You will need to register your filter in the web.config of your SharePoint site. Keep in mind there can only be one RuntimeFilter per virtual server so if you are testing on a MOSS install you will need to comment out the original AudienceManager filter before adding this one.

 

The safest place to register your filter is immediately before the ending SharePoint element </SharePoint>.

 

 <RuntimeFilter Assembly="DevConRunTimeFilter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b9e17e23dc48e734" Class="DevConRunTimeFilter.RuntimeFilter" />

 

Run IISReset and you should now be able to see the sample when you bring up the “Modify Shared Web Part” menu.

IRuntimeFilter2SampleCode.EXE_rename_to_exe