如何:为 PerformancePoint Services 表格数据源创建编辑器

上次修改时间: 2011年8月30日

在 Microsoft SharePoint Server 2010 中的 PerformancePoint Services 中,自定义编辑器使用户能够在自定义对象上设置属性。它们提供编辑控件,并检索和更新存储库中的自定义对象。有关编辑器功能的详细信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

适用范围: SharePoint Server 2010

本主题中的过程和代码示例基于自定义对象示例中的 SampleDataSourceEditor 类。此编辑器是一类瘦 Web 应用程序,用户可利用它执行以下操作:修改数据源的名称和说明、输入股票代号和指定代理服务器地址和缓存文件位置。本主题中的"示例"一节提供了该类的完整代码。

备注

建议您使用示例编辑器作为模板。该示例演示如何在 PerformancePoint Services API 中调用对象,提供可简化对存储库操作(如创建和更新对象)的调用的帮助程序对象,并演示 PerformancePoint Services 开发的最佳做法。

通过执行以下两个基本过程创建数据源编辑器,如下所示:

  • 创建和配置编辑器类

  • 定义编辑功能

若要创建自定义编辑器,请开始创建编辑器类。

创建和配置编辑器类

  1. 安装 PerformancePoint Services,或将您的扩展使用的 DLL(步骤 3 中已列出)复制到计算机上。有关详细信息,请参阅 开发方案中使用的 PerformancePoint Services DLL

  2. 在 Visual Studio 中创建 C# 类库。如果已经为您的扩展创建了类库,则添加一个新的 C# 类。

  3. 将以下 DLL 作为程序集引用添加到项目:

    • Microsoft.PerformancePoint.Scorecards.Client.dll

    • Microsoft.SharePoint.dll(由帮助程序类使用)

    示例编辑器还包含对 System.Core.dll、System.Web.dll、System.Web.Services.dll 和 System.Xml.Linq.dll 的程序集引用。可能需要其他项目引用,具体取决于您的扩展的功能。

  4. 将示例中的以下类添加到项目。您的编辑器使用这些帮助程序类与 PerformancePoint Services 存储库和缓存文件进行交互:

    • ExtensionRepositoryHelper.cs

    • DataSourceRepositoryHelper.cs

    • SampleDSCacheHandler.cs

  5. 在编辑器类中,为 Microsoft.PerformancePoint.Scorecards 命名空间添加一个 using 指令。根据扩展的功能不同,可能需要其他 using 指令。

  6. 从支持您的编辑器实现的基类继承。由于示例数据源编辑器是一个 Web 应用程序,因此它继承自 Page 类。其他实现可派生自基类,如 UserControlWebPart 类。

在创建和配置编辑器类后,必须定义您的编辑器的功能。

定义编辑功能

  1. 为可公开您希望用户查看或修改的属性的控件声明变量。示例数据源编辑器先为用户界面组件(一个 ASPX 页)中定义的 Web 服务器控件声明变量。示例编辑器还定义一个按钮控件,使用户能够提交更改。然后,此编辑器调用 CreateChildControls() 方法以使控件在此页上可用。

    备注

    编辑器定义独立于用户界面的编程逻辑。有关创建编辑器的用户界面组件的说明不在本文档范围之内。

  2. 从查询字符串检索参数,并将其设置为本地变量的值,如以下代码示例所示:

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

    有关查询字符串参数的信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

  3. 检索用于调用存储库的 DataSourceRepositoryHelper 对象,如以下代码示例所示。

    DataSourceRepositoryHelper = new DataSourceRepositoryHelper();
    
  4. 根据查询字符串参数设置数据源位置,如以下代码示例所示。

    RepositoryLocation repositoryDataSourceLocation = RepositoryLocation.CreateFromUriString(itemLocation);
    
  5. 从查询字符串检索要执行的操作(OpenItem 或 CreateItem),然后检索或创建自定义数据源,如以下代码示例所示。

    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase)) 
    {
        // Use the repository-helper object to retrieve the data source.
        datasource = dataSourceRepositoryHelper.Get(repositoryDataSourceLocation);
        if (datasource == null)
        {
            displayError("Could not retrieve the data source for editing.");
            return;
        }
    }
    else
    {
        displayError("Invalid Action.");
        return;
    }
    

    备注

    默认情况下,用户只能从 PerformancePoint 仪表板设计器创建自定义对象。若要使用户能够在仪表板设计器外部创建自定义对象,您必须添加一个菜单项,该菜单项将存储库中内容类型的 CreateItem 请求发送到您的编辑器。有关详细信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

    示例数据源编辑器执行 Page_Load 方法中的步骤 2 到步骤 5。还可使用 Page_Load 执行以下操作:初始化并验证变量和控件、填充控件以及保存自定义数据源和帮助程序对象的状态信息。

  6. 使用用户定义的更改来更新数据源。示例数据源编辑器调用 DataSourceRepositoryHelper.Update 方法以更新存储库中数据源对象的 NameDescriptionCustomData 属性。可使用 CustomData 存储序列化的对象或字符串。示例编辑器使用它来存储用户定义的股票代号、用于存储股票代号报价值的缓存文件的位置以及代理服务器地址。

    备注

    用户可编辑自定义对象的 NameDescriptionOwner("负责人")属性,并直接从仪表板设计器和 PerformancePoint Services 存储库中删除自定义对象。

  7. 调用数据源提供程序以定义列映射(如果尚未定义列映射)。

    示例数据源编辑器执行 buttonOK_Click 和 CreateCacheFile 方法中的步骤 6 和步骤 7。还可使用 buttonOK_Click 调用 AreAllInputsValid 方法以验证控件内容并检索自定义数据源和帮助程序对象的状态信息。

    **下一步:**在创建数据源编辑器(如果需要,包括其用户界面)和数据源提供程序后,部署扩展,如如何:手动注册 PerformancePoint Services 扩展中所述。有关如何安装示例数据源扩展的说明,请参阅代码示例:自定义报表、筛选器和表格数据源对象中的"安装示例报表、筛选器和数据源对象"一节。

示例

以下代码示例检索和更新存储库中的自定义表格数据源,并提供针对 ASPX 页中定义的控件的编程逻辑。

备注

您必须先按创建和配置编辑器类中所述配置开发环境,然后才能编译此代码示例。

using System;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.PerformancePoint.Scorecards;
using System.Xml.Linq;

namespace Microsoft.PerformancePoint.SDK.Samples.SampleDataSource
{
    // Represents the class that defines the sample data source editor.
    public class SampleDataSourceEditor : Page
    {

        #region Members
        // Declare private variables for the ASP.NET controls defined in the user interface.
        // The user interface is an ASPX page that defines the controls in HTML.
        private TextBox textboxName;
        private TextBox textboxDescription;
        private TextBox textboxStockSymbols;
        private TextBox textboxXMLLocation;
        private TextBox textboxProxy;
        private Label labelErrorMessage;
        private Button buttonOK;
        #endregion

        #region Page methods and events
        // Make the controls available to this class.
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            if (null == textboxProxy)
                textboxProxy = FindControl("textboxProxy") as TextBox;
            if (null == textboxName)
                textboxName = FindControl("textboxName") as TextBox;
            if (null == textboxDescription)
                textboxDescription = FindControl("textboxDescription") as TextBox;
            if (null == textboxStockSymbols)
                textboxStockSymbols = FindControl("textboxStockSymbols") as TextBox;
            if (null == textboxXMLLocation)
                textboxXMLLocation = FindControl("textboxXMLLocation") as TextBox;
            if (null == labelErrorMessage)
                labelErrorMessage = FindControl("labelErrorMessage") as Label;
            if (null == buttonOK)
                buttonOK = FindControl("buttonOK") as Button;
        }

        // 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)
        {
            // Initialize controls the first time the page loads only.
            if (!IsPostBack)
            {
                EnsureChildControls();

                DataSourceRepositoryHelper dataSourceRepositoryHelper = 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.
                    dataSourceRepositoryHelper =
                        new DataSourceRepositoryHelper();

                    // Set the data source location.
                    RepositoryLocation repositoryDataSourceLocation = RepositoryLocation.CreateFromUriString(itemLocation);

                    DataSource datasource;

                    // Retrieve the data source object by
                    // using the repository-helper object.
                    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                    {
                        datasource = dataSourceRepositoryHelper.Get(repositoryDataSourceLocation);
                        if (datasource == null)
                        {
                            displayError("Could not retrieve the data source for editing.");
                            return;
                        }
                    }
                    else
                    {
                        displayError("Invalid Action.");
                        return;

                    }

                    // Save the original data source and helper objects across page postbacks.
                    ViewState["action"] = action;
                    ViewState["datasource"] = datasource;
                    ViewState["datasourcerepositoryhelper"] = dataSourceRepositoryHelper;

                    // Populate the child controls.
                    if (null != datasource.Name)
                        textboxName.Text = datasource.Name.ToString();

                    if (null != datasource.Description)
                        textboxDescription.Text = datasource.Description.ToString();

                    if (null != datasource.CustomData)
                    {
                        string[] splitCustomData = datasource.CustomData.Split('&');
                        if (splitCustomData.Length > 2)
                        {
                            textboxStockSymbols.Text = splitCustomData[0];
                            textboxXMLLocation.Text = splitCustomData[1].Replace(@"\SampleStockQuotes.xml", string.Empty);
                            textboxProxy.Text = splitCustomData[2];
                        }
                    }
                }
                catch (Exception ex)
                {
                    displayError("An error has occurred. Please contact your administrator for more information.");
                    if (dataSourceRepositoryHelper != null)
                    {
                        // Add the exception detail to the server
                        // event log.
                        dataSourceRepositoryHelper.HandleException(ex);
                    }
                }
            }
        }

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

            // Verify that the required fields contain values.
            if (!AreAllInputsValid())
                return;

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

            // Retrieve the data source and helper objects from view state.
            string action = (string)ViewState["action"];
            DataSource datasource = (DataSource)ViewState["datasource"];
            DataSourceRepositoryHelper datasourcerepositoryhelper = (DataSourceRepositoryHelper)ViewState["datasourcerepositoryhelper"];

            // Update the data source object with form changes.
            datasource.Name.Text = textboxName.Text;
            datasource.Description.Text = textboxDescription.Text;

            // Define column mappings if they aren't already defined.
            if (datasource.DataTableMapping.ColumnMappings.Count <= 0)
            {
                datasource.DataTableMapping = WSTabularDataSourceProvider.CreateDataColumnMappings();
            }

            // Save the data source to the repository
            // by using the repository-helper object.
            try
            {
                CreateCacheFile(datasource);

                datasource.Validate();

                if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                {
                    datasourcerepositoryhelper.Update(datasource);
                }
                else
                {
                    displayError("Invalid Action.");
                }
            }
            catch (Exception ex)
            {
                displayError("An error has occurred. Please contact your administrator for more information.");
                if (datasourcerepositoryhelper != null)
                {
                    // Add the exception detail to the server event log.
                    datasourcerepositoryhelper.HandleException(ex);
                }
            }
        }
        #endregion

        #region Helper methods
        // Display 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;
        }

        // Validate the text box inputs.
        bool AreAllInputsValid()
        {
            if (string.IsNullOrEmpty(textboxProxy.Text))
            {
                labelErrorMessage.Text = "The proxy server address is required.";
                return false;
            }

            if (string.IsNullOrEmpty(textboxXMLLocation.Text))
            {
                labelErrorMessage.Text = "The location to save the cache file to is required.";
                return false;
            }

            if (string.IsNullOrEmpty(textboxName.Text))
            {
                labelErrorMessage.Text = "A data source name is required.";
                return false;
            }

            if (string.IsNullOrEmpty(textboxStockSymbols.Text))
            {
                labelErrorMessage.Text = "A stock symbol is required.";
                return false;
            }

            return true;
        }

        // Create the XML cache file at the specified location and
        // store it and the stock symbols in the CustomData
        // property of the data source.
        void CreateCacheFile(DataSource datasource)
        {
            string cacheFileLocation = string.Format("{0}\\{1}", textboxXMLLocation.Text.TrimEnd('\\'),
                                                     "SampleStockQuotes.xml");

            datasource.CustomData = string.Format("{0}&{1}&{2}", textboxStockSymbols.Text, cacheFileLocation, textboxProxy.Text);

            // Check if the cache file already exists.
            if (!File.Exists(cacheFileLocation))
            {
                // Create the cache file if it does not exist.
                XDocument doc = SampleDSCacheHandler.DefaultCacheFileContent;
                doc.Save(cacheFileLocation);
            }
        }
        #endregion
    }
}

编译代码

您必须先按创建和配置编辑器类中所述配置开发环境,然后才能编译此代码示例。

安全性

您必须使用强名称对 DLL 进行签名。此外,确保 DLL 引用的所有程序集都具有强名称。有关如何使用强名称对程序集进行签名以及如何创建公钥/私钥对的信息,请参阅How to: Create a Public/Private Key Pair

请参阅

任务

如何:为 PerformancePoint Services 表格数据源创建提供程序

概念

用于自定义 PerformancePoint Services 对象的编辑器

其他资源

为 PerformancePoint Services 创建自定义对象

SharePoint Server 2010 中的 PerformancePoint Services 的代码示例