转至元数据结尾
转至元数据起始

前一个例子介绍如何完全不使用代码,仅通过C1OlapPage控件来创建一个完整的OLAP应用。这是非常方便的,但是在大多数情况下,你也许想要某种程度上定制自己的应用以及用户界面。

持久化OLAP视图

我们首先创建一个默认视图到之前的应用。想要完成这部分工作,你需要在你的Visual Studio项目中右键单击解决方案浏览器中的项目结点,单击"Properties"条目,然后选择"Settings"选项卡,创建一个叫做"DefaultView"的字符串类型设
置:

该设置将用于在会话之间持久化视图,因此任何由用户产生的定制将在应用关闭之后自动进行保存,然后在下一次启动后进行恢复。想要实现这一功能,打开"Form1"表单,切换到编码视图,然后将下述代码添加到应用中:
private void Form1_Load(object sender, EventArgs e) { // auto-generated:
// This line of code loads data into the 'nWINDDataSet.Invoices' table.
this.invoicesTableAdapter.Fill(this.nWINDDataSet.Invoices);
// show default view: this assumes an application
// setting of type string called "DefaultView" var view = Properties.Settings.Default.DefaultView; if (!string.IsNullOrEmpty(view))
{
c1OlapPage1.ViewDefinition = view;
} else
{
// build default view now var olap = c1OlapPage1.OlapEngine; olap.BeginUpdate();
olap.RowFields.Add("ProductName"); olap.ColumnFields.Add("Country"); olap.ValueFields.Add("ExtendedPrice"); olap.EndUpdate();
}
}
// closing form, save current view as default for next time protected override void OnClosing(CancelEventArgs e)
{
// save current view as new default
Properties.Settings.Default.DefaultView = c1OlapPage1.ViewDefinition;
Properties.Settings.Default.Save();
// fire event as usual base.OnClosing(e); }
当你打开表单时,第一行应该始终如此。它是加载数据时自动生成的。
下一部分代码检查"DefaultView"设置是否已经可用。如果可用,则将其赋值给C1OlapPage.ViewDefinition属性。这将应用于整个视图设置,包括所有字段以及它们各自的属性,例如图表,表格以及报表选项。
如果"DefaultView"设置不可用,代码将创建一个视图,并在RowFields, ColumnFields以及ValueFields集合中添加字段。此视图将根据产品和国家显示销售总额(总价数值之和)。
接下来的代码重载表单的OnClosing方法,并且通过读取C1OlapPage.ViewDefinition保存当前视图,然后赋值给保存在本地的"DefaultView"设置。
如果你现在运行项目,你会注意到它将启动使用代码创建的默认视图。如果你对视图作出任何改变,关闭应用然后重启它,将会看到你的改变已经被恢复。

创建预定义视图

除了使用ViewDefinition属性通过XML字符串来获取和设置当前视图外,C1OlapPage 控件还提供ReadXml和 WriteXml方法让你将视图持久化到文件或者流中。当你在内置工具栏中单击"Load"和"Save"按钮时,这些方法已经被C1OlapPage 自动包含。
这些方法允许你非常简单的实现预定义视图。想要完成这一工作,你首先要创建一些视图,然后单击"Save"按钮保存每个视图。在本例中,我们将创建5个视图显示销售额:

  1. 产品和国家
  2. 销售人员和国家 3. 销售人员和年份
  3. 销售人员和月份
  4. 销售人员和周

一旦你创建完毕并且保存了所有的视图,你需要创建一个叫做"OlapViews.xml"的XML文件,该文件包含一个"OlapViews"节点,然后复制和粘贴你的默认视图到这个文档中。接下来,增加"id"标签到每个视图,然后给每个视图命名。视图名称将在用户界面(OLAP并没有这样要求)显示。你的XML文件实现效果应如下面所示:
<OlapViews>
<C1OlapPage id="Product vs Country">
<!-- view definition omitted... -->
<C1OlapPage id="SalesPerson vs Country">
<!-- view definition omitted... -->
<C1OlapPage id="SalesPerson vs Year">
<!-- view definition omitted... -->
<C1OlapPage id="SalesPerson vs Month">>
<!-- view definition omitted... -->
<C1OlapPage id="SalesPerson vs Weekday">
<!-- view definition omitted... -->
</OlapViews>
现在将这个文件作为资源加入到项目中,完成以下步骤实现该功能:

  1. 右键单击解决方案浏览器中的项目结点,然后单击"Properties"。
  2. 选择"Resource"选项卡,单击"Add Resource"旁边的下拉箭头。
  3. 选择"Add Existing File…"选项,选择XML文件,然后单击Open按钮。


现在视图模板已经准备就绪,我们需要在菜单中显示它们以便用户可以进行选择。想要完成这一工作,将下述代码复制到项目中:
private void Form1_Load(object sender, EventArgs e) { // auto-generated:
// This line of code loads data into the 'nWINDDataSet.Invoices' table.
this.invoicesTableAdapter.Fill(this.nwindDataSet.Invoices);
// build menu with predefined views: var doc = new System.Xml.XmlDocument(); doc.LoadXml(Properties.Resources.OlapViews); var menuView = new ToolStripDropDownButton("&View");
foreach (System.Xml.XmlNode nd in doc.SelectNodes("OlapViews/C1OlapPage"))
{
var tsi = menuView.DropDownItems.Add(nd.Attributes["id"].Value); tsi.Tag = nd;
}
menuView.DropDownItemClicked += menuView_DropDownItemClicked; c1OlapPage1.Updated += c1OlapPage1_Updated;
// add new view menu to C1OlapPage toolstrip c1OlapPage1.ToolStrip.Items.Insert(3, menuView); }
上述代码将创建一个新的下拉工具栏按钮,通过加载内含报表模板的XML文档,在报表创建时放置下拉按钮。每一个条目在它的Text属性中都包含视图的名称并且在它的Tag属性中包含了实际的XML节点。该节点将在稍后用户选中时应用到报表中。
一旦下拉按钮准备就绪,上述代码使用ToolStrip属性将其添加到C1OlapPage 中。新按钮添加到位置3,在初始的两个按钮以及初始分隔符的后面。唯一缺少的部分是当用户单击按钮选择它们时,如何将视图添加到C1OlapPage 的代码。下述代码将实现该功能:
// select a predefined view
void menuView_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
var nd = e.ClickedItem.Tag as System.Xml.XmlNode; if (nd != null)
{
// load view definition from XML c1OlapPage1.ViewDefinition = nd.OuterXml;
// show current view name in status bar
c1OlapPage1.LabelStatus.Text = nd.Attributes["id"].Value;
}
}
void c1OlapPage1_Updated(object sender, EventArgs e)
{
// clear report name after user made any changes c1OlapPage1.LabelStatus.Text = string.Empty; }
代码通过读取OuterXml属性的节点以XML字符串的形式检索报表模板,然后将其赋值给ViewDefinition属性。它同时还在C1OlapPage 状态条中使用LabelStatus属性显示视图名称。
最后,在用户对视图作出任何更改后,代码将调用Updated事件清除状态条。这种情况表明视图并不匹配从应用资源中加载的预定义视图。
C1OlapPage 公开了大部分包含组件,这样可以使定制更容易实现。你可以使用TabControl的工具栏对元素进行添加,删除或者修改等操作。并且可以使用LabelStatus属性显示状态信息。除了添加到C1OlapPage 中之外,你还可以添加其他元素到页面中。
如果你需要更深层次的定制,你也可以选择不使用C1OlapPage,创建你自己的界面,使用联通级别更低的
C1OlapPanel, C1OlapGrid和 C1OlapChart 控件。C1OlapPage 控件的源代码包含在包中,可以作为起始项目。
"Building a custom User Interface"部分的示例将告诉你如何实现这些功能。

  • 无标签