wpf 实现 table 布局控件
- 框架支持
.net4 至 .net8; visual studio 2022;
有开发者提出希望 wpf 使用 html 的 table 标签进行显示表格?
html示例如下:
<table>
<th>header 1</th>
<tr>
<td>cell 1</td>
</tr>
</table>
因为需要快速实现表格功能时,我选择基于 grid 控件,因为 grid 提供了对跨行和跨列布局的支持。
一、新建 td.cs 控件继承自 label 代码如下:
主要内容:
属性 rowspan 和 columnspan:
rowspan 和 columnspan 分别定义了行跨度和列跨度的依赖属性,设置了默认值为 1。
属性可以在 c# 或者 xaml 中进行设置和获取。
td 控件适用于在 wpf 中实现复杂的表格布局,通过行和列的跨度属性,可以灵活地控制表格中单元格的布局。
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)));
}
}
}
设置 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 设置表格线颜色。
borderthickness 设置 table 表格边框。
using system.windows.controls;
namespace wpftablegrid
{
public class th : label
{
}
}设置 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顺序。- 构造函数:注册
loaded事件处理控件的行列。 - 算出表格的行数:统计内部
tr控件的数量,加上一行(表头)。 - 算出列数:找到所有
tr中的td单元格,并根据getcolumnspan方法确定最大列数。 - 每个表头
th,设置其在表格中的位置,并调整边框。 - 循环每行
tr并处理其子控件td。 - 删除其原始父容器
tr的引用。 - 将其添加到
table的子集。 - 设置
td的行和列。 - 如果
td跨行或跨列,会更改其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 控件进行实现。对于更高级的需求,可以考虑将其修改为基于 panel,自定义列的显示方式以及实现跨行和跨列的布局。
文中 xaml 中使用 wpfdevelopers库,如果直接拷贝使用,需要确保将相关的资源和控件进行正确的替换和配置。
到此这篇关于wpf实现table布局控件的示例代码的文章就介绍到这了,更多相关wpf table布局控件内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网
发表评论