Create filter editors for PerformancePoint Services in SharePoint

Learn how to create the editor component of a custom filter extension for PerformancePoint Services.

What are custom filter editors for PerformancePoint Services?

In PerformancePoint Services, custom filter editors enable users to set properties on custom filters. Filter editors must also initialize a filter's BeginPoints property, which defines the filter beginpoint that contains parameter values for scorecard and report consumers. For more information about editor requirements and functionality, see Editors for Custom PerformancePoint Services Objects.

The following procedures and examples are based on the SampleFilterEditor class from the custom objects sample. The editor is a thin web application that enables users to modify the filter's name and description and to select the underlying data source. For the complete code for the class, see Code example: Create, retrieve, and update custom PerformancePoint Services filters in SharePoint.

We recommend that you use the sample editor as a template. The sample shows how to call objects in the PerformancePoint Services API, provides helper objects that simplify calls for repository operations (such as creating and updating objects), and demonstrates best practices for PerformancePoint Services development.

Create and configure the editor class for custom PerformancePoint Services filters

  1. Install PerformancePoint Services, or copy the DLLs that your extension uses (see step 3) to your computer. For more information, see DLLs with Class Libraries.

  2. In Visual Studio, create a C# class library. If you have created a class library for your extension, add a new C# class.

    You must sign your DLL with a strong name. In addition, ensure that all assemblies referenced by your DLL have strong names. For information about how to sign an assembly with a strong name and how to create a public/private key pair, see How to: Create a public/private key pair.

  3. Add the following DLLs as assembly references to the project:

    • Microsoft.PerformancePoint.Scorecards.Client.dll
    • Microsoft.PerformancePoint.Scorecards.ServerCommon.dll
    • Microsoft.PerformancePoint.Scorecards.ServerRendering.dll
    • Microsoft.PerformancePoint.Scorecards.Store.dll (used by helper classes)
    • Microsoft.SharePoint.dll (used by helper classes)

    The sample editor also contains assembly references to System.Web.dll and System.Web.Services.dll. Depending on your extension's functionality, other project references may be required.

  4. Add the following classes from the sample to the project. The editor uses these helper classes to interact with the PerformancePoint Services repository:

    • DataSourceConsumerHelper.cs
    • ExtensionRepositoryHelper.cs
    • FilterRepositoryHelper.cs
    • IDataSourceConsumer.cs
  5. In your editor class, add using directives for the following PerformancePoint Services namespaces:

    • Microsoft.PerformancePoint.Scorecards
    • Microsoft.PerformancePoint.Scorecards.ServerCommon
    • Microsoft.PerformancePoint.Scorecards.ServerRendering

    Depending on your extension's functionality, other using directives may be required.

  6. Inherit from the base class that supports your editor implementation. Because the sample filter editor is a web application, it inherits from the Page class. Other implementations can derive from base classes such as the UserControl class or WebPart class.

  7. Define controls that expose the properties that you want users to view or modify. The sample filter editor first declares variables for the web server controls that are defined in the user interface component, which is an ASPX page. The sample editor also defines a button control that enables users to submit changes. Then, the editor calls the CreateChildControls() method to make the controls available on the page.

    Note

    The editor defines programming logic separately from the user interface. Instructions for creating the user interface component of the editor are beyond the scope of this documentation.

    The sample filter editor performs steps 8 through 12 in the Page_Load method. Page_Load is also used to initialize and validate variables and controls, populate controls, and save state information for the custom filter and helper objects.

  8. Set the AllowUnsafeUpdates property to true. This enables the filter editor to write data to the repository without using form POST operations.

  9. Retrieve the parameters from the query string and set them as values for local variables, as shown in the following code example.

    // The URL of the site collection that contains the PerformancePoint Services repository.
    string server = Request.QueryString[ClickOnceLaunchKeys.SiteCollectionUrl];
    
    // The location of the filter in the repository.
    string itemLocation = Request.QueryString[ClickOnceLaunchKeys.ItemLocation];
    
    // The operation to perform: OpenItem or CreateItem.
    string action = Request.QueryString[ClickOnceLaunchKeys.LaunchOperation];
    

    Note

    For information about query string parameters, see Editors for Custom PerformancePoint Services Objects.

  10. Retrieve the FilterRepositoryHelper object, which is used to make calls to the repository, as shown in the following code example.

    filterRepositoryHelper = new FilterRepositoryHelper();
    
  11. Set the filter location based on the query string parameter, as shown in the following code example.

    RepositoryLocation repositoryFilterLocation = RepositoryLocation.CreateFromUriString(itemLocation);
    
  12. Retrieve the operation to perform ( OpenItem or CreateItem) from the query string, and then retrieve or create the custom filter.

    • To retrieve the custom filter, use the FilterRepositoryHelper.Get method.
    • To create the custom filter, use the Filter() constructor and define the filter's Name , RendererClassName , and SubTypeId properties. SubTypeId is the unique identifier for the filter, and it must match the subType attribute that you specify for your custom filter in the PerformancePoint Services web.config file. RendererClassName is the fully qualified name of the class that defines the renderer web server control. If it is not defined in the editor, this value defaults to the renderer class that is specified in the web.config file.
    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
    {
      // Use the repository-helper object to retrieve the filter.
      filter = filterRepositoryHelper.Get(repositoryFilterLocation);
      if (filter == null)
      {
        displayError("Could not retrieve the filter for editing.");
        return;
      }
    }
    else if (ClickOnceLaunchValues.CreateItem.Equals(action, StringComparison.OrdinalIgnoreCase))
    {
      filter = new Filter
      {
        RendererClassName = typeof(MultiSelectTreeViewControl).AssemblyQualifiedName,
        SubTypeId = "SampleFilter"
      };
    }
    

    Note

    By default, users can create custom objects from PerformancePoint Dashboard Designer only. To enable users to create a custom object outside of Dashboard Designer, you must add a menu item that sends a CreateItem request to your editor from the content type in the repository. For more information, see Editors for Custom PerformancePoint Services Objects.

  13. Retrieve the filter's underlying data source from the repository. The sample filter editor uses the FilterRepositoryHelper.DataSourceHelper property to call the DataSourceConsumerHelper.GetDataSource method, which is used to retrieve the data source by its location in the repository. This is shown in the following code example.

    if (!string.IsNullOrEmpty(filter.DataSourceLocation.ItemUrl))
    {
      RepositoryLocation repositoryDatasourceLocation = RepositoryLocation.CreateFromUriString(filter.DataSourceLocation.ItemUrl);
      datasource = filterRepositoryHelper.DataSourceHelper.GetDataSource(repositoryDatasourceLocation);
    }
    
  14. To enable users to select a data source for the filter, populate the selection control with PerformancePoint Services data sources. The PopulateDataSourceDropDown method in the sample filter editor calls the DataSourceConsumerHelper.GetDataSourcesBySourceNames method to retrieve the data sources. This is shown in the following code example.

    // The parameter contains the default server-relative URL to the PerformancePoint Data Connections Library.
    // Edit this value if you are not using the default path. A leading forward slash may not be needed.
    ICollection dataSourceCollection =
    
    filterRepositoryHelper.DataSourceHelper.GetDataSourcesBySourceNames
        ("/BICenter/Data%20Connections%20for%20PerformancePoint/",
             new[] { "WSTabularDataSource", DataSourceNames.ExcelWorkbook });
    

    The sample filter editor retrieves only two types of data source, but you can modify this method to support other data source types or to prompt the user for the type of data source to retrieve. To reference a native data source of a particular type, use the SourceName property, which returns a field from the DataSourceNames class. To reference a custom data source, use the SubTypeId property of the data source, which is the same value as the subType attribute that is registered in the PerformancePoint Services web.config file for the data source extension.

    If you modify this method, you must make the corresponding change in the GetDisplayDataInternal method in the sample filter's data provider.

  15. Define the filter beginpoint, which is represented by the BeginPoints property. This defines the source of the filter values and is required to enable the filter to send data to scorecards and reports.

    1. Create a ParameterDefinition object. BeginPoints returns a ParameterDefinitionCollection object that contains only one ParameterDefinition object.

    2. To specify the filter's data provider, set the ParameterProviderId property to the unique identifier of the data provider. This value must match the value that is returned by the data provider's GetId() method.

    3. To specify the source of the key identifiers for the filter values, set the KeyColumn property to the column in the display data table that contains the key identifiers. The sample filter editor defines this property as the "Symbol" column.

    4. To specify the source of the display values for the filter control, set the DisplayColumn property to the column in the display data table that contains the display values. The sample filter editor defines this property as the "Symbol" column.

      Note

      The display data table is returned by the DisplayValues property, and it is initialized when the filter data provider calls the GetDisplayDataInternal method. If the data table contains other columns, you can define other column mappings to provide additional functionality.

    if (0 == filter.BeginPoints.Count)
    {
      ParameterDefinition paramDef = new ParameterDefinition();
    
      // Reference the data provider.
      paramDef.ParameterProviderId = "SampleFilterDataProvider";
      paramDef.DefaultPostFormula = string.Empty;
    
      // Specify the column that contains the key identifiers and the column
      // that contains the display values. The sample uses the same column
      // for both purposes.
      // These values must match the structure of the data table that is
      // returned by the ParameterDefinition.DisplayValues property.
    
      paramDef.KeyColumn = "Symbol";
      paramDef.DisplayColumn = "Symbol";
    
      // You can use this property to store custom information for this filter.
      paramDef.CustomDefinition = string.Empty;
    
      filter.BeginPoints.Add(paramDef);
    }
    

    The sample editor defines its beginpoint in the VerifyFilter method. It also uses VerifyFilter to verify that required properties are set and to define the selection mode, which is an optional property.

  16. Initialize the filter by running the filter's query and retrieving data from the data source. The buttonOK_Click method in the sample filter editor calls the FilterRepositoryHelper.GetParameterDisplayData method to initialize the filter.

    Note

    The editor must call FilterRepositoryHelper.GetParameterDisplayData at least once before updating the filter object.

  17. Update the filter with user-defined changes. The buttonOK_Click method in the sample filter editor calls the FilterRepositoryHelper.Update method to update the filter's Name , Description , and DataSourceLocation properties in the repository. In addition, buttonOK_Click is used to validate the contents of the controls and retrieve state information for the custom filter and the helper object.

    Note

    Users can set a custom object's Name , Description , and Owner ( Person Responsible) properties and delete custom objects directly from Dashboard Designer and the PerformancePoint Services repository.

Code example: Create, retrieve, and update custom PerformancePoint Services filters in SharePoint

The following code example creates, retrieves, and updates custom filters. This code is from the editor's code-behind class, which provides the programming logic for controls that are defined in an ASPX page.

Before you can compile this code example, you must configure your development environment as described in Create and configure the editor class for a filter editor in PerformancePoint Services.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.PerformancePoint.Scorecards;
using Microsoft.PerformancePoint.Scorecards.ServerCommon;
using Microsoft.PerformancePoint.Scorecards.ServerRendering;

namespace Microsoft.PerformancePoint.SDK.Samples.SampleFilter
{

    // Represents the class that defines the sample filter editor.
    public class SampleFilterEditor : Page
    {

        // Declare private variables for the ASP.NET controls defined in the user interface.
        // The sample's user interface is an ASPX page that defines the controls in HTML.
        private TextBox textboxName;
        private TextBox textboxDescription;
        private Label labelErrorMessage;
        private DropDownList dropdownlistDataSource;
        private Button buttonOK;
        private ListBox listboxStocks;

        // Make the controls available to this class.
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            if (null == textboxName)
                textboxName = FindControl("textboxName") as TextBox;
            if (null == textboxDescription)
                textboxDescription = FindControl("textboxDescription") as TextBox;
            if (null == dropdownlistDataSource)
                dropdownlistDataSource = FindControl("dropdownlistDataSource") as DropDownList;
            if (null == labelErrorMessage)
                labelErrorMessage = FindControl("labelErrorMessage") as Label;
            if (null==buttonOK)
                buttonOK = FindControl("buttonOK") as Button;
            if (null==listboxStocks)
                listboxStocks = FindControl("listboxStocks") as ListBox;
        }

        // Handles the Load event of the Page control.
        // Methods that use a control variable should call the Control.EnsureChildControls
        // method before accessing the variable for the first time.
        protected void Page_Load(object sender, EventArgs e)
        {

            // Required to enable custom report and filter editors to
            // write data to the repository.
            ServerUtils.AllowUnsafeUpdates = true;

            // Initialize controls the first time the page loads only.
            if (!IsPostBack)
            {
                EnsureChildControls();
                FilterRepositoryHelper filterRepositoryHelper = null;
                try
                {

                    // Get information from the query string parameters.
                    string server = Request.QueryString[ClickOnceLaunchKeys.SiteCollectionUrl];
                    string itemLocation = Request.QueryString[ClickOnceLaunchKeys.ItemLocation];
                    string action = Request.QueryString[ClickOnceLaunchKeys.LaunchOperation];

                    // Validate the query string parameters.
                    if (string.IsNullOrEmpty(server) ||
                        string.IsNullOrEmpty(itemLocation) ||
                        string.IsNullOrEmpty(action))
                    {
                        displayError("Invalid URL.");
                        return;
                    }

                    // Retrieve the repository-helper object.
                    filterRepositoryHelper =
                        new FilterRepositoryHelper();

                    // Set the filter location.
                    RepositoryLocation repositoryFilterLocation = RepositoryLocation.CreateFromUriString(itemLocation);

                    Filter filter;
                    DataSource datasource = null;

                    // Retrieve or create the filter object, depending on the operation
                    // passed in the query string (OpenItem or CreateItem).
                    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                    {

                        // Retrieve the filter object by using the repository-helper object.
                        filter = filterRepositoryHelper.Get(repositoryFilterLocation);
                        if (filter == null)
                        {
                            displayError("Could not retrieve the filter for editing.");
                            return;
                        }

                    }
                    else if (ClickOnceLaunchValues.CreateItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                    {

                        // Create a filter.
                        // CreateItem requests can be sent from a SharePoint list, but
                        // you must create a custom menu item to send the request.
                        // Dashboard Designer can send edit requests only.
                        filter = new Filter
                            {

                                // Specify the class that defines the renderer
                                // web server control. The sample filter uses a native
                                // PerformancePoint Services renderer.
                                // Defaults to the value specified in the web.config file
                                RendererClassName = typeof(MultiSelectTreeViewControl).AssemblyQualifiedName,

                                // Specify the unique identifier for the filter.
                                // The SubTypeId property must match the
                                // subType attribute in the web.config file.
                                SubTypeId = "SampleFilter"
                            };
                    }
                    else
                    {
                        displayError("Invalid Action.");
                        return;
                    }

                    VerifyFilter(filter);

                    // Retrieve filter's underlying data source.
                    if (!string.IsNullOrEmpty(filter.DataSourceLocation.ItemUrl))
                    {
                        RepositoryLocation repositoryDatasourceLocation =
                            RepositoryLocation.CreateFromUriString(filter.DataSourceLocation.ItemUrl);
                        datasource =

                            // Gets a PerformancePoint Services data source by using the
                            // DataSourceHelper property to call the
                            // DataSourceConsumerHelper.GetDataSource method.
                            filterRepositoryHelper.DataSourceHelper.GetDataSource(repositoryDatasourceLocation);
                    }

                    // Save the original filter and helper objects across page postbacks.
                    ViewState["action"] = action;
                    ViewState["filter"] = filter;
                    ViewState["filterrepositoryhelper"] = filterRepositoryHelper;
                    ViewState["itemlocation"] = itemLocation;

                    // Populate the child controls.
                    textboxName.Text = filter.Name.ToString();
                    textboxDescription.Text = filter.Description.ToString();

                    // Populate the dropdownlistDataSource control with data sources of specific
                    // types from the PerformancePoint Services repository.
                    // This method looks up the passed data source in the data sources
                    // that are registered in the web.config file.
                    // Although the sample retrieves data sources of two specific types,
                    // you can modify it to prompt the user for a data source type.
                    PopulateDataSourceDropDown(datasource);

                    // Call the SelectedIndexChanged event directly to populate the
                    // listbox control with preview data.
                    dropdownlistDataSource_SelectedIndexChanged(null, null);
                }
                catch (Exception ex)
                {
                    displayError("An error has occurred. Please contact your administrator for more information.");
                    if (filterRepositoryHelper != null)
                    {
                        // Add the exception detail to the server event log.
                        filterRepositoryHelper.HandleException(ex);
                    }
                }
            }
        }

        // Handles the SelectedIndexChanged event of the dropdownlistDataSource control.
        protected void dropdownlistDataSource_SelectedIndexChanged(object sender, EventArgs e)
        {
            EnsureChildControls();

            // Check if a valid data source is selected.
            if (null != dropdownlistDataSource.SelectedItem &&
                !string.IsNullOrEmpty(dropdownlistDataSource.SelectedItem.Text))
            {
                // Retrieve the data source object.
                FilterRepositoryHelper filterRepositoryHelper =
                    (FilterRepositoryHelper)ViewState["filterrepositoryhelper"];
                string selectedDataSourceItemUrl = dropdownlistDataSource.SelectedItem.Value;

                RepositoryLocation repositoryDatasourceLocation =
                    RepositoryLocation.CreateFromUriString(selectedDataSourceItemUrl);
                DataSource datasource = filterRepositoryHelper.DataSourceHelper.GetDataSource(repositoryDatasourceLocation);
                ViewState["datasource"] = datasource;

                // Populate the listboxStocks control with the preview data for the selected
                // data source.
                PopulateListBoxData(datasource);
            }
            else
            {
                ClearStocksListBox();
            }
        }

        // Clears the listboxStocks control.
        // The sample filter works with a web service that provides stock information.
        private void ClearStocksListBox()
        {
            listboxStocks.DataSource = null;
            listboxStocks.DataBind();
            listboxStocks.Items.Clear();
        }

        // Handles the Click event of the buttonOK control.
        protected void buttonOK_Click(object sender, EventArgs e)
        {
            EnsureChildControls();

            // Verify that the controls contain values.
            if (string.IsNullOrEmpty(textboxName.Text))
            {
                labelErrorMessage.Text = "A filter name is required.";
                return;
            }
            if (dropdownlistDataSource.SelectedIndex == 0)
            {
                labelErrorMessage.Text = "A data source is required.";
                return;
            }

            // Clear any pre-existing error message.
            labelErrorMessage.Text = string.Empty;

            // Retrieve the filter, data source, and helper objects from view state.
            string action = (string)ViewState["action"];
            string itemLocation = (string) ViewState["itemlocation"];
            Filter filter = (Filter)ViewState["filter"];
            DataSource datasource = (DataSource)ViewState["datasource"];
            FilterRepositoryHelper filterRepositoryHelper = (FilterRepositoryHelper)ViewState["filterrepositoryhelper"];

            // Update the filter object with form changes.
            filter.Name.Text = textboxName.Text;
            filter.Description.Text = textboxDescription.Text;
            filter.DataSourceLocation = datasource.Location;
            foreach (ParameterDefinition parameterDefinition in filter.BeginPoints)
            {
                parameterDefinition.DisplayName = filter.Name.Text;
            }

            // Initialize the filter. This method runs the filter's query and retrieves preview data.
            filterRepositoryHelper.GetParameterDisplayData(ref filter);

            // Save the filter object to the PerformancePoint Services repository.
            try
            {
                filter.Validate();

                if (ClickOnceLaunchValues.CreateItem.Equals(action,StringComparison.OrdinalIgnoreCase))
                {
                    Filter newFilter = filterRepositoryHelper.Create(
                        string.IsNullOrEmpty(filter.Location.ItemUrl) ? itemLocation : filter.Location.ItemUrl, filter);
                    ViewState["filter"] = newFilter;
                    ViewState["action"] = ClickOnceLaunchValues.OpenItem;
                }
                else
                {
                    filterRepositoryHelper.Update(filter);
                }
            }
            catch (Exception ex)
            {
                displayError("An error has occurred. Please contact your administrator for more information.");
                if (filterRepositoryHelper != null)
                {

                    // Add the exception detail to the server event log.
                    filterRepositoryHelper.HandleException(ex);
                }
            }
        }

        // Displays the error string in the labelErrorMessage label.
        void displayError(string msg)
        {
            EnsureChildControls();

            labelErrorMessage.Text = msg;

            // Disable the OK button because the page is in an error state.
            buttonOK.Enabled = false;
            return;
        }

        // Verifies that the properties for the filter object are set.
        static void VerifyFilter(Filter filter)
        {

            if (null != filter)
            {

                // Verify that all required properties are set.
                if (string.IsNullOrEmpty(filter.SubTypeId))
                {

                    // This value must match the subType attribute specified
                    // in the web.config file.
                    filter.SubTypeId = "SampleFilter";
                }

                if (string.IsNullOrEmpty(filter.RendererClassName))
                {
                    filter.RendererClassName = typeof (MultiSelectTreeViewControl).AssemblyQualifiedName;
                }

                // Define the BeginPoints property so the filter can send a parameter value to
                // scorecards and reports.
                // The value must be from the KeyColumn of the display
                // DataTable object, which is defined in the data provider. The data table is
                // returned by the FilterRepositoryHelper.GetParameterDisplayData method.
                // A filter has one beginpoint only, and it is represented by a
                // ParameterDefinition object. The ParameterDefinition object defines how
                // the filter accesses the data.
                if (0 == filter.BeginPoints.Count)
                {
                    ParameterDefinition paramDef = new ParameterDefinition
                                                       {
                                                           // This value must match the value returned
                                                           // by the data provider's GetId method.
                                                           ParameterProviderId = "SampleFilterDataProvider",

                                                           // Reference the data provider.
                                                           DefaultPostFormula = string.Empty,

                                                           // Specify the column that contains
                                                           // the key identifiers and the column
                                                           // that contains the display values.
                                                           // The sample uses the same column
                                                           // for both purposes.
                                                           // These values must match the structure
                                                           // of the data table that is returned
                                                           // by the ParameterDefinition.DisplayValues property.
                                                           KeyColumn = "Symbol",
                                                           DisplayColumn = "Symbol",

                                                           // You can use this property to store
                                                           // extra information for this filter.
                                                           CustomDefinition = string.Empty
                                                       };
                    filter.BeginPoints.Add(paramDef);
                }

                // Set optional properties. The renderer can return multiple values.
                filter.SelectionMode = FilterSelectionMode.MultiSelect;
            }
        }

        // Populates the dropdownlistDataSource control.
        void PopulateDataSourceDropDown(DataSource filterDataSource)
        {
            EnsureChildControls();

            FilterRepositoryHelper filterRepositoryHelper =
                (FilterRepositoryHelper)ViewState["filterrepositoryhelper"];

            // Retrieve data sources from the repository by using the DataSourceHelper
            // property to call the DataSourceConsumerHelper object.
            // If you modify the types of data source to retrieve, you must make the corresponding
            // change in the filter's data provider.
            // The parameter contains the default server-relative URL to the PerformancePoint Data Connections Library.
            // Edit this value if you are not using the default path. A leading forward slash may not be needed.
            ICollection dataSourceCollection = filterRepositoryHelper.DataSourceHelper.GetDataSourcesBySourceNames("/BICenter/Data%20Connections%20for%20PerformancePoint/",
                new[] { "WSTabularDataSource", DataSourceNames.ExcelWorkbook });
            if (null == dataSourceCollection)
            {
                displayError("No available data sources were found.");
                return;
            }

            // Create a list of name/value pairs for the dropdownlistDataSource control.
            var dataSources = new List<KeyValuePair<string, string>>();
            int selectedIndex = 0;
            int i = 1;
            dataSources.Add(new KeyValuePair<string, string>(string.Empty, string.Empty));

            foreach (DataSource ds in dataSourceCollection)
            {
                dataSources.Add(new KeyValuePair<string, string>(ds.Name.Text, ds.Location.ItemUrl));

                // Check if the entry is the originally selected data source.
                if ((filterDataSource != null) &amp;&amp;
                    (string.Compare(ds.Name.Text, filterDataSource.Name.Text) == 0))
                {
                    selectedIndex = i;
                }
                ++i;
            }

            dropdownlistDataSource.DataSource = dataSources;
            dropdownlistDataSource.DataTextField = "Key";
            dropdownlistDataSource.DataValueField = "Value";
            dropdownlistDataSource.DataBind();
            dropdownlistDataSource.SelectedIndex = selectedIndex;
        }


        // Populate the list box data.
        void PopulateListBoxData(DataSource datasource)
        {
            EnsureChildControls();

            ClearStocksListBox();

            FilterRepositoryHelper filterRepositoryHelper =
                (FilterRepositoryHelper)ViewState["filterrepositoryhelper"];

            // Retrieve the first 100 rows of the preview data from the data source
            DataSet dataSet = filterRepositoryHelper.DataSourceHelper.GetDataSet(100, datasource);

            if (null != dataSet &amp;&amp; null != dataSet.Tables[0])
            {
                listboxStocks.DataTextField = "Symbol";
                listboxStocks.DataValueField = "Value";
                listboxStocks.DataSource = dataSet.Tables[0];
                listboxStocks.DataBind();
            }
        }
    }
}

Next steps

After you create a filter editor (including its user interface, if required) and a data provider, deploy the extension as described in How to: Manually Register PerformancePoint Services Extensions.

See also