WPF實(shí)現(xiàn)Table布局控件的示例代碼
WPF 實(shí)現(xiàn) Table 布局控件
- 框架支持
.NET4 至 .NET8
; Visual Studio 2022
;
有開(kāi)發(fā)者提出希望 WPF
使用 HTML
的 table
標(biāo)簽進(jìn)行顯示表格?
html
示例如下:
<table> <th>Header 1</th> <tr> <td>Cell 1</td> </tr> </table>
因?yàn)樾枰焖賹?shí)現(xiàn)表格功能時(shí),我選擇基于 Grid
控件,因?yàn)?Grid
提供了對(duì)跨行和跨列布局的支持。
一、新建 Td.cs
控件繼承自 Label
代碼如下:
主要內(nèi)容:
屬性 RowSpan
和 ColumnSpan
:
RowSpan
和 ColumnSpan
分別定義了行跨度和列跨度的依賴屬性,設(shè)置了默認(rèn)值為 1
。
屬性可以在 C#
或者 XAML
中進(jìn)行設(shè)置和獲取。
Td
控件適用于在 WPF
中實(shí)現(xiàn)復(fù)雜的表格布局,通過(guò)行和列的跨度屬性,可以靈活地控制表格中單元格的布局。
using System.Windows; using System.Windows.Controls; namespace WPFTableGrid { public class Td : Label { public static readonly DependencyProperty RowSpanProperty = DependencyProperty.Register("RowSpan", typeof(int), typeof(Td), new PropertyMetadata(1)); public int RowSpan { get { return (int)GetValue(RowSpanProperty); } set { SetValue(RowSpanProperty, value); } } public static readonly DependencyProperty ColumnSpanProperty = DependencyProperty.Register("ColumnSpan", typeof(int), typeof(Td), new PropertyMetadata(1)); public int ColumnSpan { get { return (int)GetValue(ColumnSpanProperty); } set { SetValue(ColumnSpanProperty, value); } } static Td() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Td), new FrameworkPropertyMetadata(typeof(Td))); } } }
設(shè)置 Td
控件的 Style
<Style TargetType="local:Td"> <Setter Property="Background" Value="White" /> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style>
二、新建 Tr.cs
繼承自 Grid
,代表表格中的一行代碼如下:
using System.Windows.Controls; namespace WPFTableGrid { public class Tr : Grid { } }
三、新建 Th.cs
繼承自 Label
,表示表頭的單元格代碼如下:
BorderBrush
設(shè)置表格線顏色。
BorderThickness
設(shè)置 Table
表格邊框。
using System.Windows.Controls; namespace WPFTableGrid { public class Th : Label { } }
設(shè)置 Th
控件的 Style
<Style TargetType="local:Th"> <Setter Property="Background" Value="LightGray" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style>
四、新建 Table.cs
繼承自 Grid
控件,支持子控件行和列的定義。代碼如下:
_zIndex
記錄控件的Z
順序。- 構(gòu)造函數(shù):注冊(cè)
Loaded
事件處理控件的行列。 - 算出表格的行數(shù):統(tǒng)計(jì)內(nèi)部
Tr
控件的數(shù)量,加上一行(表頭)。 - 算出列數(shù):找到所有
Tr
中的Td
單元格,并根據(jù)GetColumnSpan
方法確定最大列數(shù)。 - 每個(gè)表頭
Th
,設(shè)置其在表格中的位置,并調(diào)整邊框。 - 循環(huán)每行
Tr
并處理其子控件Td
。 - 刪除其原始父容器
Tr
的引用。 - 將其添加到
Table
的子集。 - 設(shè)置
Td
的行和列。 - 如果
Td
跨行或跨列,會(huì)更改其Z
順序。
using System.Windows; using System.Windows.Controls; namespace WPFTableGrid { public class Table : Grid { private int _zIndex = 1; public Table() { Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { UpdateControl(); } private void UpdateControl() { RowDefinitions.Clear(); ColumnDefinitions.Clear(); if (InternalChildren.Count > 0) { var rows = InternalChildren.OfType<Tr>().Count() + 1; for (int i = 0; i < rows; i++) RowDefinitions.Add(new RowDefinition()); var columns = InternalChildren.OfType<Tr>().Max(child => child.Children.OfType<Td>().Sum(td => GetColumnSpan(td))); for (int i = 0; i < columns; i++) ColumnDefinitions.Add(new ColumnDefinition()); var index = 0; var list = InternalChildren.OfType<Tr>().ToList(); var ths = InternalChildren.OfType<Th>().ToList(); var hIndex = 0; for (int j = 0; j < ths.Count; j++) { Th header = ths[j]; if (j == 0) header.BorderThickness = new Thickness(1, 1, 1, 1); else header.BorderThickness = new Thickness(0, 1, 1, 1); SetRow(header, index); SetColumn(header, hIndex); hIndex++; } for (int j = 0; j < list.Count; j++) { index++; Tr row = list[j]; var cIndex = 0; var childElements = row.Children.OfType<Td>().ToList(); foreach (var cell in childElements) { if (cell.Parent is Panel oldParent) { oldParent.Children.Remove(cell); } Children.Add(cell); if (cIndex == 0) cell.BorderThickness = new Thickness(1, 0, 1, 1); else cell.BorderThickness = new Thickness(0, 0, 1, 1); SetRow(cell, index); SetColumn(cell, cIndex); cell.SetValue(RowSpanProperty, cell.RowSpan); cell.SetValue(ColumnSpanProperty, cell.ColumnSpan); if (cell.RowSpan > 1 || cell.ColumnSpan > 1) { SetZIndex(cell, _zIndex); _zIndex++; } cIndex++; } } } } } }
四、新建 TableExample.xaml
示例代碼如下:
<wd:Window x:Class="WPFTableGrid.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFTableGrid" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" Title="WPFDevelopers - Table" Width="800" Height="450" mc:Ignorable="d"> <Window.Resources> <Style TargetType="local:Th"> <Setter Property="Background" Value="LightGray" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style> <Style TargetType="local:Td"> <Setter Property="Background" Value="White" /> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Button Margin="0,10,0,0" HorizontalAlignment="Center" Click="BtnHeader_Click" Content="Header" Style="{StaticResource WD.DangerPrimaryButton}" /> <local:Table Grid.Row="1" Margin="10"> <local:Th Content="Header 1" /> <local:Th Content="Header 2" /> <local:Th Content="Header 3" /> <local:Tr> <local:Td Content="Cell 1" /> <local:Td> <TextBlock Margin="5" Text="Cell 2" /> </local:Td> <local:Td> <TextBlock Margin="5" Text="Cell 3" /> </local:Td> </local:Tr> <local:Tr> <local:Td RowSpan="3"> <TextBlock Margin="4" Text="Cell 4" /> </local:Td> <local:Td> <TextBlock Margin="5" Text="Cell 5" /> </local:Td> <local:Td> <TextBlock Margin="5" Text="Cell 6" /> </local:Td> </local:Tr> <local:Tr> <local:Td> <TextBlock Margin="5" Text="Cell 7" /> </local:Td> <local:Td ColumnSpan="2"> <TextBlock Margin="5" Text="Cell 8" /> </local:Td> <local:Td> <TextBlock Margin="5" Text="Cell 9" /> </local:Td> </local:Tr> </local:Table> </Grid> </wd:Window>
效果圖
該方案基于 Grid
控件進(jìn)行實(shí)現(xiàn)。對(duì)于更高級(jí)的需求,可以考慮將其修改為基于 Panel
,自定義列的顯示方式以及實(shí)現(xiàn)跨行和跨列的布局。
文中 XAML
中使用 WPFDevelopers庫(kù),如果直接拷貝使用,需要確保將相關(guān)的資源和控件進(jìn)行正確的替換和配置。
到此這篇關(guān)于WPF實(shí)現(xiàn)Table布局控件的示例代碼的文章就介紹到這了,更多相關(guān)WPF Table布局控件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
詳解C# List<T>的Contains,Exists,Any,Where性能對(duì)比
這篇文章主要介紹了詳解C# List<T>的Contains,Exists,Any,Where性能對(duì)比,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12C# JsonHelper 操作輔助類(lèi),拿來(lái)直接用
本文總結(jié)了一些常用的JSON操作輔助類(lèi),包括轉(zhuǎn)換、判斷、Ajax異步等操作,希望能幫到大家。2016-05-05C#中把字符串String轉(zhuǎn)換為整型Int的小例子
這篇文章主要介紹了C#中把字符串String轉(zhuǎn)換為整型Int的小例子,本文使用TryParse方法實(shí)現(xiàn)轉(zhuǎn)換,需要的朋友可以參考下2014-08-08C#/VB.NET讀取條碼類(lèi)型及條碼在圖片中的坐標(biāo)位置實(shí)例
我們?cè)趧?chuàng)建條形碼時(shí),如果以圖片的方式將創(chuàng)建好的條碼保存到指定文件夾路徑,可以在程序中直接加載圖片使用;已生成的條碼圖片,需要通過(guò)讀取圖片中的條碼信息,如條碼類(lèi)型、條碼繪制區(qū)域在圖片中的四個(gè)頂點(diǎn)坐標(biāo)位置等,可參考本文中的方法2023-10-10

C#客戶端HttpClient請(qǐng)求認(rèn)證及數(shù)據(jù)傳輸