zoukankan      html  css  js  c++  java
  • Silverlight 自定义Grid实线

    (一)前言

    由于项目的需求,必须用silverlight实现表格形式的预警图。在Silverlight中表格形式的最佳方式为Grid,虽然Grid提供了ShowGridLine属性,但是该线条为虚线,外观看起来很不协调。开始的时候,本人打算在每个Cell中采用Border来设置线条。这样虽然可以实现实线,但是每行每列都会涉及到单元格与单元格之间的重叠,以及第一列与最后一列、第一行与最后一行的线条控制需要复杂的算法来控制,因此这种方式肯定是行不通的(不是实现不了,而是将简单的问题复杂化了)。下面讲解的是另外一种方式,采用添加直线的方法来绘制实线。

    (二)类图设计

    下面所涉及的都是针对于特定情况下的Grid实线绘制,仅仅是本人项目中抽象出来的简单版本而已(仅仅是思路,具体实现涉及到信息安全,哥可扛不起,哈哈,现在的绝对与项目无关),类图如下:

    实现的效果图如下:

    (三)具体实现

    这里主要可以控制第一行的高度,第一列的宽度,Grid在容器Canvas的间隔(LeftMargin,TopMargin),其他单元格的宽度、高度,Grid的行数,Grid的列数。至于实线的具体绘制封装在基类GridFormatter中,具体单元格的内容由子类来实现(可能用于很多场景),第一行的标题,第一列的内容都有子类AlertTable去实现。这里涉及到一些简单的数学运算,应该是很容易理解的。实现多态的话,只要实现抽象类GridFormatter的抽象方法SetTableContent即可。

    基类GridFormatter的具体实现

    (1)调用的方法主要是如下2个,主要参数都标识了,应该比较清晰易懂(至于判断参数是否小于0,这里就不打算写上去了,大家只要知道这些参数具体是什么就可以了):

     1 /// <summary>
     2         /// 实例化GridFormatter类。
     3         /// </summary>
     4         /// <param name="leftMargin">左边距。</param>
     5         /// <param name="topMargin">右边距。</param>
     6         /// <param name="rowCount">行数。</param>
     7         /// <param name="columnCount">列数。</param>
     8         public GridFormatter(int leftMargin, int topMargin,
     9             int rowCount,int columnCount)
    10         {
    11             this.LeftMargin = leftMargin;
    12             this.TopMargin = topMargin;
    13             this.RowCount = rowCount;
    14             this.ColumnCount = columnCount;
    15         }
    16 
    17         /// <summary>
    18         /// 创建Grid的内容。
    19         /// </summary>
    20         /// <param name="canvas">Canvas容器。</param>
    21         /// <param name="cellWidth">单元格宽度。(第一行第一列的除外)</param>
    22         /// <param name="cellHeight">单元格高度。(第一行第一列的除外)</param>
    23         /// <param name="firstColumnWidth">第一列的宽度。</param>
    24         /// <param name="firstRowHeight">第一行的高度。</param>
    25         public void Create(Canvas canvas, int cellWidth, int cellHeight,
    26             int firstColumnWidth, int firstRowHeight) 
    27         {
    28             if (canvas == null)
    29             {
    30                 throw new ArgumentNullException("The container's parameter is null!");
    31             }
    32             
    33             this.CellWidth = cellWidth;
    34             this.CellHeight = cellHeight;
    35             this.FirstColumnWidth = firstColumnWidth;
    36             this.FirstRowHeight = firstRowHeight;
    37 
    38             AddGrid(canvas);
    39             CreateTable();
    40         }

    (2)接下来我们需要设置表格的架构,也就是说设置表格的行数和列数,以及这些单元格的宽度和高度,代码如下:

     1         private void SetTableSchema()
     2         {
     3             for (int rowIndex = 0; rowIndex < this.RowCount; rowIndex++)
     4             {
     5                 int height = rowIndex == 0 ? this.FirstRowHeight : this.CellHeight;
     6                 RowDefinition rd = new RowDefinition();
     7                 rd.Height = new GridLength(height);
     8                 this.Grid.RowDefinitions.Add(rd);
     9             }
    10            
    11             for (int columnIndex = 0; columnIndex < this.ColumnCount; columnIndex++)
    12             {
    13                 int width = columnIndex == 0 ? this.FirstColumnWidth : this.CellWidth;
    14                 ColumnDefinition cd = new ColumnDefinition();
    15                 cd.Width = new GridLength(width);
    16                 this.Grid.ColumnDefinitions.Add(cd);
    17             }
    18         }

    如果是第一行,设置高度为this.FirstRowHeight。如果是第一列,设置宽度为this.FirstColumnWidth。具体由如下2行代码设置高度和宽度,

    5                 int height = rowIndex == 0 ? this.FirstRowHeight : this.CellHeight;

    13               int width = columnIndex == 0 ? this.FirstColumnWidth : this.CellWidth;

    (3)设置Grid的大小以及容器Canvas的大小(宽度和高度),因为Canvas必须设置大小才能正常显示,而且可以通过Canvas才能灵活的设置控件的绝对位置。代码如下:

    1         private void SetSize()
    2         {
    3             this.Width = this.CellWidth * (this.ColumnCount - 1+ this.FirstColumnWidth;
    4             this.Height = this.CellHeight * (this.RowCount - 1+ this.FirstRowHeight;
    5             this.Container.Width = this.Width + this.LeftMargin * 2;
    6             this.Container.Height = this.Height + this.TopMargin * 2;
    7         }

    下面的2行代码将使Grid在Canvas中居中显示:

    5             this.Container.Width = this.Width + this.LeftMargin * 2;
    6             this.Container.Height = this.Height + this.TopMargin * 2;

     

    (4)设置水平线,代码如下:

     1         private void SetHorizontalLines()
     2         {
     3             AddLine(this.LeftMargin, this.TopMargin, this.Width + this.LeftMargin, this.TopMargin);
     4 
     5             for (int index = 0; index < this.RowCount; index++)
     6             {
     7                 int y1 = index * this.CellHeight + this.TopMargin + this.FirstRowHeight;
     8                 int y2 = y1;
     9                 AddLine(this.LeftMargin, y1, this.Width + this.LeftMargin, y2);
    10             }
    11         }

    第三行   3   AddLine(this.LeftMargin, this.TopMargin, this.Width + this.LeftMargin, this.TopMargin);主要是绘制最上面的水平线。

    for循环将设置其他的水平线。int y1 = index * this.CellHeight + this.TopMargin + this.FirstRowHeight;设置y坐标。因为从该行开始,y坐标将加上this.TopMargin(顶部间隔)以及 this.FirstRowHeight(第一行的高度)。

     

    (5)设置竖线,代码如下:

     1         private void SetVerticalLines()
     2         {
     3             AddLine(this.LeftMargin, this.TopMargin, this.LeftMargin, this.TopMargin + this.Height);
     4 
     5             for (int index = 0; index < this.ColumnCount; index++)
     6             {
     7                 int x1 = index * this.CellWidth + this.LeftMargin + this.FirstColumnWidth;
     8                 int x2 = x1;
     9                 AddLine(x1, this.TopMargin, x2, this.TopMargin + this.Height);
    10             }
    11         }

    第三行   3   AddLine(this.LeftMargin, this.TopMargin, this.LeftMargin, this.TopMargin + this.Height);主要是绘制最左边的竖线。

    for循环将设置其他的竖线。int x1 = index * this.CellWidth + this.LeftMargin + this.FirstColumnWidth;设置x坐标。因为从该列开始,x坐标将加上this.LeftMargin (左边间隔)以及 this.FirstColumnWidth(第一列的宽度)。

    (6)实现单元格的内容

    对于单元格具体内容的设置,将由子类实现public abstract void SetTableContent();

     1     public class AlertTable : GridFormatter
     2     {
     3         public AlertTable(int leftPadding, int topPadding,
     4             int rowCount, int columnCount)
     5             : base(leftPadding, topPadding, rowCount, columnCount)
     6         {
     7         }
     8 
     9         public override void SetTableContent()
    10         {
    11             SetFirstRowContent();
    12             SetFirstColumnContent();
    13             SetContent();
    14         }
    15 
    16         private void SetContent()
    17         {          
    18             for (int rowIndex = 1; rowIndex < base.RowCount; rowIndex++)
    19             {
    20                 for (int columnIndex = 1; columnIndex < base.ColumnCount; columnIndex++)
    21                 {
    22                     //SetCellUserControl(rowIndex, columnIndex);
    23                 }           
    24             }
    25         }
    26 
    27         private void SetFirstColumnContent()
    28         {
    29             for (int index = 1; index < base.RowCount; index++)
    30             {
    31                 base.SetCellTextContent(index, 0"Row " + index.ToString());
    32             }
    33         }
    34 
    35         private void SetFirstRowContent()
    36         {
    37             for (int index = 1; index < base.ColumnCount; index++)
    38             {
    39                 base.SetCellTextContent(0, index, "Column Head " + index.ToString());
    40             }
    41         }
    42     }


    子类将重写父类的方法,如第9行:public override void SetTableContent();具体由子类来填充单元格的内容。

     

    具体实现只有100行左右的代码,



    (四)总结

    针对于容器中控件的绝对位置的控制采用Canvas(通常需要涉及到具体坐标点的控制),灵活运用各种控件来进行操作。对于Grid需要设置实线的话必须自定义绘制相关实线(目前Grid是虚线的,很不协调)。这种方式是由局限性的,只是针对于特定场景最有效。最近几个月跟着款哥混,水平直线飙升,多谢款哥。一个人有多优秀,要看他有谁指点,跟对人,做对事,至理名言啊,哈哈....

    其实项目中哥还是没采用这种多态的方式,没必要,这样的场景只是偶尔出现,不需要多态。上面涉及的只是很简单的抽象,很多时候,代码需要不断的设计、重写来完善。有时候,方法也没必要设计得非常灵活,因为更加灵活的话意味着复杂性的提高。

    源代码下载:/Files/jasenkin/Jasen.Silverlight.GridSample.rar

  • 相关阅读:
    JavaScript判断字符串的字符长度(中文占两个字符)
    MessageQueue 一 简单的创建和读取
    HttpWebResponse返回信息
    IDEA 快捷操作 Windows
    不带头结点的单链表的创建、插入、删除。
    二叉树的深度
    【Python爬虫实战】pywin32 安装后出现 import win32api ImportError DLL load failed
    【Python爬虫实战】Scrapy框架的安装 搬运工亲测有效
    【Python爬虫实战】多线程爬虫---糗事百科段子爬取
    【Python爬虫实战】微信爬虫
  • 原文地址:https://www.cnblogs.com/jasenkin/p/silverlight_grid_line_drawing.html
Copyright © 2011-2022 走看看