Silverlight for KPI

题外话先:早些时候一同事问我KPI到底是咋回事,我用标准的解释方法说了好几遍都没听懂,后来干脆直接跟他说------GDP,他叹了口气,委屈的说知道了.(GDP是公司近段时间提出的个人产值的指标,达到这个就保持你的工资,达不到就扣你20%工资,有啥概念还有比这更深入人心呢,,可恶的经济危机啊)

写此篇受到李兄很大的启发.一直以来就有用类似WPF来实现BI的想法,只是由于个人原因迟迟没有实现.不过最近看到WXWinter()工作流作品深受鼓舞.

 

为什么要wpf/silverlight for KPI or BI?笔者评估过很多工具或者第三方组件,都是纯asp.net control,他们在运行起来需要加载大量的javascript,容易导致浏览器死掉,而且还要区分浏览器类型和版本.通过flash或者silverlight这种方式多少可以避开这样的问题,而且展现形式要更灵活.

先写KPI,原因是发现这个实现起来相对来说要简单一些,本文最终完成的效果是这个样子的:


关于KPI的详细解释,请参考微软的这篇文档.这里简要按照个人的理解说一下一些用到的概念:

首先是目标”,其实按照字面理解就可以,就是一个用来衡量的标准,””,就是实际是多少,这个值和目标做比较,KPI应用中,通常没有达到的就显示个红灯以示警告,跟这个值差不多就显示一个黄灯,超过目标一个指定的范围就现实一个绿灯,这种通过红黄绿的标识可以理解为其中的状态”.

明确以上的概念,那么在silverlight中显示KPI就不难了,实际上就是怎么把状态值显示成相关的图片.

首先,silverlight中要面对数据通信的问题,silverlight不像WPF 桌面应用,客户端无法ADO.NET,更别提ADOMD.NET,所以需要通过WebService或者其它的类似方案,WebService里引用ADOMD.NETAnalysis Services进行操作.

查询的语法通常是如下的格式(SQLServer2005/2008通用的SSAS):

SELECT

   { KPIValue("Channel Revenue"),

     KPIGoal("Channel Revenue"),

     KPIStatus("Channel Revenue"),

     KPITrend("Channel Revenue")

   } ON Columns,

Descendants

   ( { [Date].[Fiscal].[Fiscal Year].&[2002],

       [Date].[Fiscal].[Fiscal Year].&[2003],

       [Date].[Fiscal].[Fiscal Year].&[2004]

     }, [Date].[Fiscal].[Fiscal Quarter]

   ) ON Rows

FROM [Adventure Works]

 

查询的结果通常如下图所示:

为了大家能在下载后看到KPI效果图,本文省略服务编写的步骤(如果有必要会在续篇中详细说明),另外大家很可能没有对应版本的分析服务,所以本文的数据是简单的测试数据,大致如下:

List<People> source = new List<People>();

 

source.Add(new People { name = "北京市", value1 = 1532, value2 = 851, field1 = 1, field2 = 0, field3 = 0, field4 = 1 });

source.Add(new People { name = "上海市", value1 = 358, value2 = 1785, field1 = -1, field2 = 0, field3 = -1, field4 = 0 });

source.Add(new People { name = "深圳市", value1 = 2564, value2 = 3584, field1 = 1, field2 = 1, field3 = -1, field4 = 0 });

source.Add(new People { name = "天津市", value1 = 1256, value2 = 258, field1 = -1, field2 = -1, field3 = -1, field4 = -1 });

source.Add(new People { name = "长春市", value1 = 3112, value2 = 2586, field1 = 1, field2 = 1, field3 = 1, field4 = 0 });

source.Add(new People { name = "沈阳市", value1 = 1584, value2 = 1258, field1 = -1, field2 = -1, field3 = -1, field4 = 0 });

source.Add(new People { name = "青岛市", value1 = 3587, value2 = 1256, field1 = 0, field2 = 0, field3 = -1, field4 = 0 });

 

dgTest.ItemsSource = source;

 

没错,这里用到的就是Silverlight2中的DataGrid,这个控件是个很灵活的控件.实际上到silverlight这一层处理就很简单了,因为它接收的除了目标值等这样的信息外,KPI状态值如上所示就是简单的状态值.

接下来需要做绑定值的转换,通常单元格里接收到的值就是-1,0,1(当然也会有-1,-0.3,0,0.3,1这样的情况,本文只考虑三种情况),所以这里的问题是如何把这样的值转换成小红灯,小黄等或者小绿灯这样的控件.这样的图片来源很广泛,可以在素材网站里找,也可以用微软sqlserver下现成的,就像李兄在文中提到的.不过在silverlight下需要多做一个工作,就是把sqlserver带的这些gif图片转成jpg,否则会出问题.Sqlserver中带了好几个样式,挑自己觉得好看的用fireworks这样的工具转一下就ok.


关于值转换这里有一个跟webappwinform程序都不大一样的地方,笔者认为也是最别扭的一个地方.按照之前的理解,KPI状态显示封装成一个usercontrol,然后暴露出一个属性供DataGrid的模板列中传递绑定的值给它就可以了,然后usercontrol里获得这个值决定显示哪张图片.但在把绑定的值给usercontrol的这个属性的时候出现了莫名其妙的问题.还好在qqwpf silverlight10458228里得到高人的指点,Converter.于是我在yahoo里搜索(中文网站上资料太少),按照其方法写了如下类.

 public class KPIImageConverter : IValueConverter

 {

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

     {

         int kpivalue = (int)value;

 

         BitmapImage source=new BitmapImage();

 

         switch (kpivalue)

         {

             case -1:

                 source.UriSource = new Uri("Images/KPI/stoplight_single0.jpg", UriKind.Relative);

                 break;

             case 0:

                 source.UriSource = new Uri("Images/KPI/stoplight_single1.jpg", UriKind.Relative);

                 break;

             case 1:

                 source.UriSource = new Uri("Images/KPI/stoplight_single2.jpg", UriKind.Relative);

                 break;

         }

 

         return source;

     }

 

     public object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture)

     {

         //Visibility visibility = (Visibility)value;

         //return (visibility == Visibility.Visible);

         return null;

     }

 }

然后在页面里做如下声明:

<UserControl.Resources>

        <SilverlightApplication1:KPIImageConverter x:Key="KPIValueConverter" />

</UserControl.Resources>

 

然后用DataGrid的模板列,这里的思路跟asp.net的差不多.

<data:DataGridTemplateColumn Header="帅哥产量状态" Width="80">

    <data:DataGridTemplateColumn.CellTemplate>

        <DataTemplate>

            <StackPanel>

                <Image Width="16" Height="16" Source="{Binding field1, Converter={StaticResource KPIValueConverter}}" />

            </StackPanel>

        </DataTemplate>

    </data:DataGridTemplateColumn.CellTemplate>

</data:DataGridTemplateColumn>

 

基本上实现的时候步骤和需要注意的地方就是这些,特意在这里说明一下,好让更多碰到类似问题的朋友都能找到解决的方法.此文描述的方法适用于SQLServer2005SQLServer2008中的Analysis Services.

最后,请注意crossdomain的问题,请看我之前关于此的描述:

http://www.cnblogs.com/aspnetx/archive/2008/04/19/1161734.html

 

总结:

总体来说WPF for BI是个不错的方案,不过让我感到奇怪的是国内外还没有见到有人做过相关的应用,多少可能是由于BI到底要render到什么程度很难找到一个标准,但确实不应该质疑WPF或者Silverlight的能力.

 

本文所提及的代码在这里下载.

 

相关资源:

微软的示例数据库,数据仓库,分析模型下载,2000 2005的:

http://www.codeplex.com/MSFTDBProdSamples

如何在SQLServer中定义和浏览KPI

http://msdn.microsoft.com/zh-cn/library/ms166869(SQL.90).aspx

posted @ 2008-11-06 10:02  哥本哈士奇(aspnetx)  阅读(2389)  评论(11编辑  收藏  举报