ComponentOne OLAP for WinForms帮助文档
构建定制用户界面


上个章节中所有的例子都使用了C1OlapPage 控件,控件包含了完整的UI因此只需要很少甚至不需要编写代码。在本章节中,我们将尝试不使用C1OlapPage创建一个OLAP应用。这将创建一个完整的定制UI,通过使用C1OlapGrid, C1OlapChart, 和其他标准的 .NET控件实现。

应用完整的源代码可以从”CustomUI”示例中查看。

下图显示应用的设计视图:

在表单的上部有一个面板显示应用标题。在表单右侧安置了一个垂直的工具栏控件,其中包含三组按钮。最上面的分组允许用户选择三种预定义视图中的一种,销售人员的销售额,产品或是国家。下一个分组允许用户在产品价格上应用一个数据库过滤器(昂贵,中等或是廉价)。最后一个按钮提供报表。

报表剩下的区域被一个左侧显示C1OlapGrid 以及右侧显示C1OlapChart 的脚本容器填充。控件将显示当前选中的视图。

表单还包含一个C1OlapPrintDocument 组件,主要用于生成报表。该组件在图片上是不可见的,因为它仅在表单下层的托盘区域显示。C1OlapPrintDocument 组件通过OlapGrid 和OlapChart属性连接到页面上的OLAP控件,这些属性将在设计阶段完成设置。

最后,表单上还有一个C1OlapPanel 控件。它的Visible属性设置为false,因此用户将不会看到它。这个不可见的控件主要用于作为表格和图表的数据源,它将负责数据过滤以及汇总数据。表格和图表都含有它们自己C1OlapPanel 中的DataSource属性。

一旦所有的控件就位,让我们添加代码,连接它们然后让应用开始工作。

首先,让我们获取数据,并将其赋值给C1OlapPanel:

private void Form1_Load(object sender, EventArgs e)
{
    // load data
    var da = new OleDbDataAdapter("select * from Invoices", 
      GetConnectionString());
    var dt = new DataTable();
    da.Fill(dt);
 
    // assign it to C1OlapPanel that is driving the app
    this.c1OlapPanel1.DataSource = dt;
 
    // start with the SalesPerson view, all products
    _btnSalesperson.PerformClick();
    _btnAllPrices.PerformClick();
}

这些代码使用DataAdapter从NorthWind数据库中获取数据,然后将结果DataTable赋值给C1OlapPanel.DataSource属性。然后使用PerformClick方法来模拟单击两个按钮,初始化当前视图和过滤器.
选择当前视图按钮事件句柄的代码如下所示:

 
void _btnSalesperson_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    BuildView("Salesperson");
}
void _btnProduct_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    BuildView("ProductName");
}
void _btnCountry_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    BuildView("Country");
}

所有的句柄都使用BuildView助手方法,该方法如下所示:

// rebuild the view after a button was clicked
void BuildView(string fieldName)
{
    // get olap engine
    var olap = c1OlapPanel1.OlapEngine;
 
    // stop updating until done
    olap.BeginUpdate();
 
    // format order dates to group by year
    var f = olap.Fields["OrderDate"];
    f.Format = "yyyy";
 
    // clear all fields
    olap.RowFields.Clear();
    olap.ColumnFields.Clear();
    olap.ValueFields.Clear();
 
    // build up view
    olap.ColumnFields.Add("OrderDate");
    olap.RowFields.Add(fieldName);
    olap.ValueFields.Add("ExtendedPrice");
 
    // restore updates
    olap.EndUpdate();
}

BuildView方法获取一个C1OlapPanel 对象提供的C1OlapEngine对象,并且立即调用BeginUpdate方法停止更新直到完成了新的视图定义。这样做能提高性能。

代码设置”OrderDate”字段的格式为”yyyy”,因此销售额将通过年份来进行分组。清除掉引擎中的RowFields, ColumnFields, 和 ValueFields集合来重新生成视图,然后添加想要显示的字段。调用者传入的”fieldName”参数仅包含一个字段的名称,并且本例中该参数将在视图中被改动。
当所有这些都完成之后,代码调用EndUpdate方法,C1OlapPanel将更新输出表。

在运行程序之前,让我们看一下实现过滤的代码。事件句柄如下所示:

void _btnExpensive_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    SetPriceFilter("Expensive Products (price > $50)", 50, double.MaxValue);
}
void _btnModerate_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    SetPriceFilter("Moderately Priced Products ($20 < price < $50)", 20, 50);
}
void _btnInexpensive_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    SetPriceFilter("Inexpensive Products (price < $20)", 0, 20);
}
void _btnAllProducts_Click(object sender, EventArgs e)
{
    CheckButton(sender);
    SetPriceFilter("All Products", 0, double.MaxValue);
}

所有的句柄都使用SetPriceFilter助手方法,该方法如下所示:

// apply a filter to the product price
void SetPriceFilter(string footerText, double min, double max)
{
    // get olap engine
    var olap = c1OlapPanel1.OlapEngine;
 
    // stop updating until done
    olap.BeginUpdate();
 
    // make sure unit price field is active in the view
    var field = olap.Fields["UnitPrice"];
    olap.FilterFields.Add(field);
 
    // customize the filter to apply the condition
    var filter = field.Filter;
    filter.Clear();
    filter.Condition1.Operator = 
      C1.Olap.ConditionOperator.GreaterThanOrEqualTo;
    filter.Condition1.Parameter = min;
    filter.Condition2.Operator = 
      C1.Olap.ConditionOperator.LessThanOrEqualTo;
    filter.Condition2.Parameter = max;
 
    // restore updates
    olap.EndUpdate();
 
    // set report footer
    c1OlapPrintDocument1.FooterText = footerText;
}

和之前类似,代码获取到C1OlapEngine的引用,然后立即调用BeginUpdate方法。

随后,它获取到”UnitPrice”字段的引用,这将用于过滤数据。”UnitPrice”字段将添加到引擎的FilterFields集合中,因此过滤器可以在当前视图中应用。

这是一个非常重要的细节。如果一个字段不存在与任何视图集合(RowFields, ValueFields, FilterFields)中,它就不能包含在视图中,而且它的过滤器属性无法通过任何方式影响视图。

代码接下来将通过设置两个视图中包含值的取值范围,从而对”UnitPrice”字段的过滤器属性进行设置。该范围通过”min”和”max”两个参数来定义。除了使用条件,你还能以列表形式提供将要包含在视图中的数值来实现这一效果。添加条件通常更合适处理数字值和列表,而不是字符串数值和枚举类型。

最后,代码调用EndUpdate方法,然后设置C1OlapPrintDocument的FooterText属性,之后它将可以自动的显示在任何报表中。

上述方法使用了另一个叫做CheckButton助手方法,方法如下所示:

// show which button was pressed
void CheckButton(object pressedButton)
{
    var btn = pressedButton as ToolStripButton;
    btn.Checked = true;
 
    var items = btn.Owner.Items;
    var index = items.IndexOf(btn);
    for (int i = index + 1; i < items.Count; i++)
    {
        if (!(items[i] is ToolStripButton)) break;
        ((ToolStripButton)items[i]).Checked = false;
    }
    for (int i = index - 1; i > 0 && !(items[i] is ToolStripSeparator); i--)
    {
        if (!(items[i] is ToolStripButton)) break;
        ((ToolStripButton)items[i]).Checked = false;
    }
}

这一方法让工具栏中的按钮以单选按钮的形式出现。当它们其中一个被点击后,同分组内的其他按钮将失效。

应用几乎完成了。你可以现在就运行它,测试应用的不同视图和过滤能力,就像下图中显示的那样:

这个视图中显示所有产品的销售额,通过月份和国家进行分组。请注意图表中是如何显示接近$300,000的数值。

如果你单击”$$$ Expensive”按钮,过滤器将应用到视图中,你立即就能发现改变。请注意现在图表中是如何显示接近$80,000的数值。大额数值将占有三分之一的销售额。


应用最后缺少的部分是生成报表。用户已经能够将OlapGrid中的数据复制到Excel中,并且可以打印或者保存这些结果。但是我们可以让它变得更简单,允许他们直接通过应用打印或者创建PDF文件。

想要完成这一功能,让我们添加部分代码到句柄中。单击”Reprot…”按钮,代码十分简单:

void _btnReport_Click(object sender, EventArgs e)
{
    using (var dlg = new C1.Win.Olap.C1OlapPrintPreviewDialog())
    {
        dlg.Document = c1OlapPrintDocument1;
        dlg.StartPosition = FormStartPosition.Manual;
        dlg.Bounds = this.Bounds;
        dlg.ShowDialog(this);
    }
}

如果你已经在.NET中完成过打印,代码应该与此类似。它首先实例化一个C1OlapPrintPreviewDialog对象。这个类类似于标准的PrintPreviewDialog类,但是它增加了导出PDF文件的能力。

代码中设置对话框的Document属性,初始化它的位置,然后显示对话框。如果你现在运行程序,单击”Report…”按钮,你将会看到一个像下面一样的对话框:

通过这个对话框,用户可以修改页面布局,打印或是导出PDF文件。

 

 


产品网站:http://www.gcpowertools.com.cn 咨询热线:4006576008 ©2015 西安葡萄城