• 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

  • 相关阅读:
    条目二十八《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》
    条目二十六《iterator优先于const_iterator、reverse_iterator以及const_reverse_iterator》
    ubuntu16.04 能启动mysql服务
    《[MySQL技术内幕:SQL编程》读书笔记
    条目二十五《熟悉非标准的散列容器》
    稳健的漫步~~~
    条目二十四《当效率至关重要时,请在map::operator[]与map::insert之间谨慎做出选择》
    条目二十三《考虑用排序的vector替代关联容器》
    条目二十一《总是让比较函数在等值情况下返回false》
    条目二十二《切勿修改set或multiset的键》
  • 原文地址:https://www.cnblogs.com/aspnetx/p/1327842.html
Copyright © 2020-2023  润新知