狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

WPF實現html中的table控件

freeflydom
2024年3月28日 17:8 本文熱度 648

前言

  相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控件也能實現,但是使用起來的體驗感并不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控件,用這種方法你需要控制每個Border的邊框,并且在一堆Bordr中找到Grid.Row,Grid.Column來確定位置,明明很簡單的一個功能,硬是耗費了大量時間。Grid的這種設計雖然功能很強大,但是同時也導致了操作繁瑣可讀性非常差的問題。此時做過web開發的人肯定很想念html中的table元素,沒錯,我也是這樣想的,如果能把html中的table元素搬到WPF中,那問題就輕松解決了,今天我們就來解決這個問題。

 

一、準備工作

    我們先來認識一下table元素,其實最開始的網頁功能相對簡單,table元素主要用于展示文本和基本的排版。然而隨著html標準的更新,table元素越來越復雜,很多功能在不同的標準中寫法可能不一樣,甚至有的功能只能在css中實現,這種情況我們成全照搬html中的寫法肯定不現實,也完全沒必要。所以必須做一個取舍。由于WPF中并沒有css的概念,所以我們盡量舍棄css中的寫法,使用WPF中類似的屬性寫法來開發,以下為統計出來的可用屬性。

 

二、需求分析

    既然我們要復刻一個東西,第一步肯定是要先搞清楚這個東西的內在邏輯,所以我們先來看看html中的table元素是怎么回事。

2.1 table結構

<table>

  <tr>

    <th>header1</th>

    <th>header2</th>

    <th>header3</th>

  </tr>

  <tr>

    <td>value1</td>

    <td>value2</td>

    <td>value3</td>

  </tr>

  <tr>

    <td>value4</td>

    <td>value5</td>

    <td>value6</td>

  </tr>

</table>

 2.1.1 table

    table為表格根元素,table內可以放置多個tr。

    2.1.2 tr 

    tr表示表格中的一行,一行可以放置若干個td。

    2.1.3 td

   td為表格單元格,td可以設置rowspan屬性合并多個行,可以設置colspan合并多個列。

 

2.2 尺寸單位

    2.2.1適用范圍

    table的width,height屬性,tr的height屬性,td的width,heigth屬性。

    2.2.2 取值范圍

    1. 百度比(例:width="50%")

    2. 像素(:width="500")

    3. 不設置(自動計算)

       

2.3 布局邏輯

    2.3.1 table

       2.3.1.1 width="50%"

       寬度占可用空間的50%,當父控件尺寸改變時會重新計算寬度,如果所有td子元素的尺寸之合大于table寬度(width="50%"),table寬度==Sum(td.width)。

       2.3.1.2 width="500"

       寬度占500像素,當父控件尺寸改變時不會重新計算寬度,如果所有td子元素的尺寸之合大于table寬度(width="500"),table寬度==Sum(td.width)。

       2.3.1.3 不設置寬度

      不設置寬度的情況下,寬度根據td子元素的寬度計算,Sum(td.width)。

 

    2.3.2 tr

        2.3.2.1 height="50%"

        高度占table元素總高的50%,當父控件尺寸改變時會重新計算高度,當tr中高度最高的td超過了tr的50%時,整行高度以該td的高度為準。

        2.3.2.2 height="500"

        高度占500像素,當父控件尺寸改變時會重新計算高度,當tr中高度最高的td超過了tr的500像素時,整行高度以該td的高度為準。

        2.3.2.3 不設置高度

        不設置高度的情況下,以最高的td子元素為準。

 

    2.3.3 td

        2.3.3.1 width="50%"

        寬度占table寬度的50%,當剩余寬度不足以分配給其它列時會壓縮該列的50%寬度,分配給其它列。該列的實際寬度以該列所有td的最大寬度為準。

        2.3.3.2 width="50"

        寬度占50像素,當剩余寬度不足以分配給其它列時會壓縮該列的50像素寬度,分配給其它列。該列的實際寬度以該列所有td的最大寬度為準。

        2.3.3.3 不設置寬度

        不設置寬度的情況下,如果其它設置了寬度的列分配完寬度后,剩余寬度大于所有td的最小寬度的總合,那么未設置寬度的列會平均分配剩余的寬度,如果剩余的寬度小于所有td最小寬度的總合,那么所有td的寬度按最小寬度分配,其它已設置寬度的列則壓縮寬度。該列的實際寬度以該列所有td的最大寬度為準。

        2.3.3.4 height="50%"

        高度占table度的50%,當剩余度不足以分配給其它時會壓縮該的50%度,分配給其它行。該行的實際度以該行所有td的最大度為準。如果最高td的高度大于tr,則以最高的td為準,如果小于tr,則以tr的高度為準。

        2.3.3.5 height="50"

        高度占50像素,當剩余度不足以分配給其它行時會壓縮該行的50像素度,分配給其它行。該行的實際度以該行所有td的最大度為準。如果最高td的高度大于tr,則以最高的td為準,如果小于tr,則以tr的高度為準。

        2.3.3.6 不設置高度

        不設置高度的情況下,如果其它設置了度的行分配完度后,剩余度大于所有td的最小度的總,那么未設置度的行會平均分配剩余的度,如果剩余的度小于所有td最小度的總合,那么所有td的度按最小度分配,其它已設置度的行則壓縮度。該行的實際度以該列所有td的最大度為準。

 

 

三、能實現

  通過對需求的分析,我們知道至少應該有3個類來實現表格功能,分別是Table、Tr、Td,我們下面來看看怎么來實現它們。

3.1 Table控件

 

  Table是一個在界面上需要呈現的元素,該控件主要處理布局及排列,不需要控件模板,所以不應該繼承自Control類,那么可不可以繼承自Panel呢,明顯也不行,Panel的尺寸及布局系統繼承自FrameworkElement,并不能給它的寬度設置Width="50%"這種值,所以它不僅不能繼承自Panel,也不能繼承自FrameworkElement,所以Table應該繼承自UIElement類,我們需要在Table寫自己的尺寸及布局管理功能,以下為Talbe的示例代碼。

[ContentProperty("Rows")]

public class Table : UIElement

{

    /// <summary>

    /// 獲取或設置行

    /// </summary>

    public TrCollection Rows

    {

        get { return (TrCollection)GetValue(RowsProperty); }

        private set { SetValue(RowsProperty, value); }

    }


    public static readonly DependencyProperty RowsProperty =

        DependencyProperty.Register("Rows", typeof(TrCollection), typeof(Table));


    /// <summary>

    /// 獲取或設置寬度

    /// </summary>

    public TableLength Width

    {

        get { return (TableLength)GetValue(WidthProperty); }

        set { SetValue(WidthProperty, value); }

    }


    public static readonly DependencyProperty WidthProperty =

        DependencyProperty.Register("Width", typeof(TableLength), typeof(Table));


    /// <summary>

    /// 獲取或設置高度

    /// </summary>

    public TableLength Height

    {

        get { return (TableLength)GetValue(HeightProperty); }

        set { SetValue(HeightProperty, value); }

    }


    public static readonly DependencyProperty HeightProperty =

        DependencyProperty.Register("Height", typeof(TableLength), typeof(Table));

}

3.2 Tr

    Tr在Table里主要的作用是表達邏輯關系,不需要在界面上呈現,所以我們可以讓它繼承自DependencyObject,可以綁定屬性就行了,以下為示例代碼。

[ContentProperty("Cells")]

public class Tr : DependencyObject

{

    /// <summary>

    /// 獲取或設置單元格

    /// </summary>

    public TdCollection Cells

    {

        get { return (TdCollection)GetValue(CellsProperty); }

        private set { SetValue(CellsProperty, value); }

    }


    public static readonly DependencyProperty CellsProperty =

        DependencyProperty.Register("Cells", typeof(TdCollection), typeof(Tr));


    /// <summary>

    /// 獲取或設置高度

    /// </summary>

    public TableLength Height

    {

        get { return (TableLength)GetValue(HeightProperty); }

        set { SetValue(HeightProperty, value); }

    }


    public static readonly DependencyProperty HeightProperty =

        DependencyProperty.Register("Height", typeof(TableLength), typeof(Tr));

}

3.3 Td

    Td的情況與Table類似,需要在界面上呈現,并且有自己的尺寸及布局邏輯,所以繼承自UIElement,以下為示例代碼。

public class Td : UIElement

{

    /// <summary>

    /// 獲取或設置需要跨的列數

    /// </summary>

    public int ColSpan

    {

        get { return (int)GetValue(ColSpanProperty); }

        set { SetValue(ColSpanProperty, value); }

    }


    public static readonly DependencyProperty ColSpanProperty =

        DependencyProperty.Register("ColSpan", typeof(int), typeof(Td), new PropertyMetadata(1));


    /// <summary>

    /// 獲取或設置需要跨的行數

    /// </summary>

    public int RowSpan

    {

        get { return (int)GetValue(RowSpanProperty); }

        set { SetValue(RowSpanProperty, value); }

    }


    public static readonly DependencyProperty RowSpanProperty =

        DependencyProperty.Register("RowSpan", typeof(int), typeof(Td), new PropertyMetadata(1));


    /// <summary>

    /// 獲取或設置寬度

    /// </summary>

    public TableLength Width

    {

        get { return (TableLength)GetValue(WidthProperty); }

        set { SetValue(WidthProperty, value); }

    }


    public static readonly DependencyProperty WidthProperty =

        DependencyProperty.Register("Width", typeof(TableLength), typeof(Table));


    /// <summary>

    /// 獲取或設置高度

    /// </summary>

    public TableLength Height

    {

        get { return (TableLength)GetValue(HeightProperty); }

        set { SetValue(HeightProperty, value); }

    }


    public static readonly DependencyProperty HeightProperty =

        DependencyProperty.Register("Height", typeof(TableLength), typeof(Table));

}

3.4.1 MeasureCore()

    該方法傳入一個名為availableSize的Size參數,該參數為控件可用的最大尺寸,我們需要通過這個參數計算各個單元格的排列位置及尺寸,并根據排列情況返回一個控件的期望尺寸,以下為實現的大致流程。

    1 通過Table的Height及Width參數計算出真實的尺寸;

    2 讀取Table的Tr屬性,取出所有Td,并定義一個二維數組將所有Td存放進去(Td[n,n]),如果Td的RowSpan或ColSpan參數大于1則將被合并的位置存入一個null。

    3 根據第2步的填充結果再定義一個存放坐標的二維數據(Size[n,n]);

    4 測量Td子元素的尺寸,計算每個單元格實際尺寸,根據Td子元素尺寸計算是否需要壓縮尺寸,計算完成后將單元格的尺寸存入第3步的數組中;

    5 根據第3步保存的尺寸數據計算單元格跨行或跨列后的尺寸;

    6 將計算出的Table實際尺寸返回給MeasureCore方法,以供下一步排列使用;

 

    3.4.2 ArrangeCore()

    該方法處理子控件的位置排列,循環調用每一個單元格的Arrange()方法,傳入測量位置及尺寸就可以了。

 

    3.4.3 OnRender()

    該方法讀取BorderColor、BgColor等參數畫線及填充顏色,表格的外觀都是由它畫出來的。

 

四、行效果

4.1 默認效果

<qs:Table

    Width="50%"

    Height="50%"

    Align="Center"

    Border="1 solid red"

    Valign="Middle">

    <qs:Tr>

        <qs:Th>11</qs:Th>

        <qs:Th>12</qs:Th>

        <qs:Th>13</qs:Th>

        <qs:Th>14</qs:Th>

        <qs:Th>15</qs:Th>

        <qs:Th>16</qs:Th>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>21</qs:Td>

        <qs:Td>22</qs:Td>

        <qs:Td>23</qs:Td>

        <qs:Td>24</qs:Td>

        <qs:Td>25</qs:Td>

        <qs:Td>26</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>31</qs:Td>

        <qs:Td>32</qs:Td>

        <qs:Td>33</qs:Td>

        <qs:Td>34</qs:Td>

        <qs:Td>35</qs:Td>

        <qs:Td>36</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>41</qs:Td>

        <qs:Td>42</qs:Td>

        <qs:Td>43</qs:Td>

        <qs:Td>44</qs:Td>

        <qs:Td>45</qs:Td>

        <qs:Td>46</qs:Td>

    </qs:Tr>

</qs:Table>

4.2 合并相鄰的線

 

<qs:Table

    Width="50%"

    Height="50%"

    Align="Center"

    Border="1 solid red collapse"

    Valign="Middle">

    <qs:Tr>

        <qs:Th>11</qs:Th>

        <qs:Th>12</qs:Th>

        <qs:Th>13</qs:Th>

        <qs:Th>14</qs:Th>

        <qs:Th>15</qs:Th>

        <qs:Th>16</qs:Th>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>21</qs:Td>

        <qs:Td>22</qs:Td>

        <qs:Td>23</qs:Td>

        <qs:Td>24</qs:Td>

        <qs:Td>25</qs:Td>

        <qs:Td>26</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>31</qs:Td>

        <qs:Td>32</qs:Td>

        <qs:Td>33</qs:Td>

        <qs:Td>34</qs:Td>

        <qs:Td>35</qs:Td>

        <qs:Td>36</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>41</qs:Td>

        <qs:Td>42</qs:Td>

        <qs:Td>43</qs:Td>

        <qs:Td>44</qs:Td>

        <qs:Td>45</qs:Td>

        <qs:Td>46</qs:Td>

    </qs:Tr>

</qs:Table>

4.3 合并單元格

 

<qs:Table

    Width="50%"

    Height="50%"

    Align="Center"

    Border="1 solid red collapse"

    Valign="Middle">

    <qs:Tr>

        <qs:Th>11</qs:Th>

        <qs:Th>12</qs:Th>

        <qs:Th>13</qs:Th>

        <qs:Th>14</qs:Th>

        <qs:Th>15</qs:Th>

        <qs:Th>16</qs:Th>

    </qs:Tr>

    <qs:Tr>

        <qs:Td ColSpan="6">21</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td RowSpan="2">31</qs:Td>

        <qs:Td>32</qs:Td>

        <qs:Td ColSpan="2" RowSpan="2">33</qs:Td>

        <qs:Td>35</qs:Td>

        <qs:Td RowSpan="2">36</qs:Td>

    </qs:Tr>

    <qs:Tr>

        <qs:Td>42</qs:Td>

        <qs:Td>45</qs:Td>

    </qs:Tr>

</qs:Table>

4.4 綜合案例

 

<qs:Table

       Width="50%"

       Height="50%"

       Align="Center"

       Border="1 solid Black collapse"

       Valign="Middle">

    <qs:Tr

           Height="40"

           Align="Center"

           BgColor="#FFAAAAAA"

           Valign="Middle">

        <qs:Th Width="40" BgColor="#FFAAAAAA">11</qs:Th>

        <qs:Th Width="10%">12</qs:Th>

        <qs:Th>13</qs:Th>

        <qs:Th>14</qs:Th>

        <qs:Th>15</qs:Th>

        <qs:Th>16</qs:Th>

    </qs:Tr>

    <qs:Tr

           Height="30%"

           Align="Center"

           BgColor="#FF5F5FF1"

           Valign="Middle">

        <qs:Td BgColor="#FFAAAAAA">21</qs:Td>

        <qs:Td>22</qs:Td>

        <qs:Td Width="20%">23</qs:Td>

        <qs:Td>24</qs:Td>

        <qs:Td>25</qs:Td>

        <qs:Td>26</qs:Td>

    </qs:Tr>

    <qs:Tr

           Height="30%"

           Align="Center"

           BgColor="#FFEA8633"

           Valign="Middle">

        <qs:Td BgColor="#FFAAAAAA">31</qs:Td>

        <qs:Td>32</qs:Td>

        <qs:Td>33</qs:Td>

        <qs:Td>34</qs:Td>

        <qs:Td>35</qs:Td>

        <qs:Td>36</qs:Td>

    </qs:Tr>

    <qs:Tr

           Height="30%"

           Align="Center"

           BgColor="#FF5F5FF1"

           Valign="Middle">

        <qs:Td BgColor="#FFAAAAAA">41</qs:Td>

        <qs:Td>42</qs:Td>

        <qs:Td>43</qs:Td>

        <qs:Td>44</qs:Td>

        <qs:Td Width="150">45</qs:Td>

        <qs:Td>46</qs:Td>

    </qs:Tr>

</qs:Table>

4.5 課表

 

<qs:Table

    Width="600"

    Height="250"

    Align="Center"

    Border="1 solid black collapse"

    Valign="Middle">

    <qs:Tr

        Height="60"

        Align="Center"

        BgColor="#FFE5E5E5"

        Valign="Middle">

        <qs:Th ColSpan="2">

            <TextBlock Text="課時/日期" />

        </qs:Th>

        <qs:Th>星期一</qs:Th>

        <qs:Th>星期二</qs:Th>

        <qs:Th>星期三</qs:Th>

        <qs:Th>星期四</qs:Th>

        <qs:Th>星期五</qs:Th>

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td RowSpan="4">上午</qs:Td>

        <qs:Td Width="100">第1節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td>第2節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td>第3節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td>第4節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td RowSpan="2">上午</qs:Td>

        <qs:Td Width="100">第5節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

    <qs:Tr Align="Center" Valign="Middle">

        <qs:Td>第6節</qs:Td>

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

        <qs:Td />

    </qs:Tr>

</qs:Table>


轉自博客園,作者趨時軟件https://www.cnblogs.com/qushi2020/p/18096836


該文章在 2024/3/28 17:09:39 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved