ZXUI.Themes.Sample 0.2.21-alpha

This is a prerelease version of ZXUI.Themes.Sample.
dotnet add package ZXUI.Themes.Sample --version 0.2.21-alpha
                    
NuGet\Install-Package ZXUI.Themes.Sample -Version 0.2.21-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ZXUI.Themes.Sample" Version="0.2.21-alpha" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ZXUI.Themes.Sample" Version="0.2.21-alpha" />
                    
Directory.Packages.props
<PackageReference Include="ZXUI.Themes.Sample" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ZXUI.Themes.Sample --version 0.2.21-alpha
                    
#r "nuget: ZXUI.Themes.Sample, 0.2.21-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ZXUI.Themes.Sample@0.2.21-alpha
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ZXUI.Themes.Sample&version=0.2.21-alpha&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ZXUI.Themes.Sample&version=0.2.21-alpha&prerelease
                    
Install as a Cake Tool

ZXUI

一套基于 Avalonia 的轻量线条风 UI 控件库,提供表格、组合按钮、评分、加载动画、十六进制输入等控件,支持明 / 暗双主题。

  • ZXUI.Controls:控件逻辑
  • ZXUI.Themes.Sample:线条风主题(明 / 暗双主题)
  • ZXUI.Svg:轻量矢量图标子库(SvgSource / SvgIcon / {z:Svg uri} 标记扩展;可独立安装给其他 Avalonia 项目用)

安装

dotnet add package ZXUI.Controls
dotnet add package ZXUI.Themes.Sample
# 矢量图标(可选;ZXUI.Controls 已传递依赖)
dotnet add package ZXUI.Svg

引入主题

在 App.axaml 中加载主题:

<Application xmlns:zx="https://zxml.dev/themes/sample"
             xmlns:z="https://zxml.dev/controls">
    <Application.Styles>
        <zx:SampleTheme />
    </Application.Styles>
</Application>

控件一览

控件 用途
DataGridTable 可编辑表格,支持选择、编辑、复制粘贴、分页、列筛选、行增删
ComposeButton 组合按钮,主操作 + 下拉菜单
RatingControl 星级评分
LoadingRing 圆圈加载动画
HexTextBox 十六进制输入框
TextLabel 随主题变色的文字

ZXUI 的图标方案(ZXUI.Svg 集成)

ZXUI 内部用 ZXUI.Svg 渲染图标,已自带一组 chevron 资源文件作为内置样例。下载安装 ZXUI.Themes.Sample 后即可直接使用。

内置图标

ZXUI.Themes.Sample/Assets/Icons/ 下提供 5 个 viewBox="0 0 24 24" + stroke="currentColor" + stroke-width="2" 的 Feather 风格 chevron:

文件 用途
chevron-down.svg ComposeButton 默认 ▼ 图标
chevron-first.svg / prev.svg / next.svg / last.svg DataGridTable 分页栏 4 个按钮

在 ZXUI 主题中的用法

ZXUI 主题里的图标都遵循这套约定:


<z:SvgIcon Width="12" Height="12" StrokeWidth="2"
           Source="{z:Svg avares://ZXUI.Themes.Sample/Assets/Icons/chevron-first.svg}"
           Foreground="{DynamicResource ZXTextMutedColor}"
           Stretch="Uniform" />


<z:SvgIcon Width="12" Height="12" StrokeWidth="2"
           Source="{TemplateBinding ChevronIconSource}"
           Foreground="{DynamicResource ZXTextMutedColor}" />


<z:SvgIcon Width="12" Height="12" StrokeWidth="3"
           Foreground="White" />


<z:SvgIcon Width="12" Height="12" StrokeWidth="3"
           Foreground="{DynamicResource ZXColumnMenuArrowBrush}" />

ComposeButton.ChevronIconSource 默认值:

defaultValue: new SvgSource("avares://ZXUI.Themes.Sample/Assets/Icons/chevron-down.svg");

业务方传自己的 SvgSource / IImage 即可替换图标;置 null 隐藏图标。

ZXUI 的设计约定(图标)

ZXUI 内置图标的尺寸 / 粗细遵循:

维度 档位 取值
尺寸 mini / small / regular / large 12 / 16 / 20 / 24 px
描边 light / regular / bold 1 / 2 / 3 px

由调用方通过 Width / Height 和 StrokeWidth 直接设置,无需在资源端做多版本维护。颜色统一接令牌(ZXTextMutedBrush / ZXColumnMenuArrowBrush / ZXFillBackgroundBrush 等),主题切换时跟随 Light / Dark 自动变换。


字体

ZXUI 内置了一套全局字体方案:默认走 Source Han Serif CN(思源宋体 CN,SIL OFL 1.1 开源字体,已随 ZXUI.Themes.Sample 包发布到 Assets/Fonts/),所有文本承载控件(TextBlock / TextBox / Button / CheckBox / …)默认就会用它。

自带字体

字体文件 注册方式
Assets/Fonts/SourceHanSerifCN-Regular.otf SampleTheme 构造时通过 EmbeddedFontCollection 注册到 FontManager.Current
Assets/Fonts/SourceHanSerifCN-SemiBold.otf 同上;表头、分区标题等 SemiBold 字重自动命中

下游消费者零配置:装好包、写 <zx-sample:SampleTheme/>,字体立即可用。

换字体(3 种方式,从轻到重)

① 覆盖默认 token(推荐)

SampleTheme/Themes/Tokens.axaml 里有个 ZXFontFamily 字体令牌,业务方在自己的 App.axaml 里 override 它即可,无需改 ZXUI 源码:

<Application.Styles>
    <zx-sample:SampleTheme />

    
    <Style Selector="TextBlock">
        <Setter Property="FontFamily" Value="Inter" />
    </Style>
    <Style Selector="TemplatedControl">
        <Setter Property="FontFamily" Value="Inter" />
    </Style>
</Application.Styles>

Inter / Helvetica / Source Han Sans / 思源黑体 等任意字体名都行。

② 引入自有字体 + 显式 FontFamily

如果字体不在系统里(比如私有定制字体),需要先把字体打进自己的项目:

a. 资源化:


<AvaloniaResource Include="Assets/Fonts/MyBrand.ttf" />

b. 在 App.axaml.cs 里注册(早于 App.Run() 启动):

protected override void OnFrameworkInitializationCompleted()
{
    if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
    {
        var fontUri = new Uri("avares://MyApp/Assets/Fonts/");
        var collection = new EmbeddedFontCollection(
            new Uri("fonts:MyApp"), fontUri);
        FontManager.Current.AddFontCollection(collection);
    }
    base.OnFrameworkInitializationCompleted();
}

c. XAML 引用:

<Setter Property="FontFamily" Value="avares://MyApp/Assets/Fonts/MyBrand.ttf#My Brand" />
③ 完全禁用 ZXUI 默认字体

如果只想保留 ZXUI 控件库(不要主题 / 不要默认字体),只引用 ZXUI.Controls 一个包即可 —— 字体注册逻辑只在 ZXUI.Themes.Sample 里,控件库本身不强制任何字体。

字体相关 FAQ

Q: 改了 ZXFontFamily 但没生效? A: <Style> 的优先级是"后定义覆盖先定义"。SampleTheme 里的默认 Style 在加载主题时已注册,覆盖 Style 要写在 <zx-sample:SampleTheme/> 之后。

Q: 西文字符也想用中文渲染? A: Source Han Serif CN 内部已含英文字形(西文部分渲染较朴素)。如果西文要更精致,加 Inter 作为回退字体:

<Setter Property="FontFamily" Value="Source Han Serif CN, Inter" />

Avalonia 字体回退链:当前字体缺字形时自动试下一个。

Q: 为什么 ZXUI 用 TemplatedControl 作为选择器? A: TextBlock 走 TextElement.FontFamily,其他文本控件(Button / TextBox / TextLabel / ComboBox / …)走 TemplatedControl.FontFamily。属性定义在两条不同的继承链上,合并写在一条 Style 里 Avalonia 会报 AVLN2000,所以分两条 Style。详细原因见源码注释。


控件

DataGridTable

Excel 式可编辑表格。

<z:DataGridTable ItemsSource="{Binding People}">
    <z:DataGridTable.Columns>
        <z:DataGridTableColumn Header="姓名" BindingPath="Name" />
        <z:DataGridTableColumn Header="年龄" BindingPath="Age" Width="80" />
        <z:DataGridTableColumn Header="职位" BindingPath="Role" IsEditable="False" />
    </z:DataGridTable.Columns>
</z:DataGridTable>
交互
操作 效果
单击 / 拖动 选中单元格 / 框出矩形选区
Ctrl + 点击 加选不相邻的格
Shift + 点击 / 方向键 从锚点扩展选区
双击 或 F2 就地编辑,Enter 提交、Esc 取消
Ctrl+C / Ctrl+V 复制粘贴(Excel 兼容 TSV)
点击行号 选中整行;拖动可连选多行
拖动行号 重排行顺序
Esc 清除选区
列定义 DataGridTableColumn
属性 说明
Header 列标题
BindingPath 绑定的数据属性名,支持点号嵌套(如 Source.Name)
Width 列宽(GridLength),默认按内容自适应
IsEditable 是否可编辑,默认 true
HorizontalContentAlignment 对齐方式:Left(默认)、Center、Right、Stretch
CellTemplate 自定义单元格模板(如下拉、复选框)
IsColumnMenuEnabled 该列是否显示列编辑菜单箭头,默认 true
Id 列稳定标识,用于布局保存
自定义单元格模板

用 CellTemplate 在单元格里放任意控件(复选框、下拉、按钮等)。模板内绑定到行数据:

<z:DataGridTable ItemsSource="{Binding People}">
    <z:DataGridTable.Columns>
        <z:DataGridTableColumn Header="姓名" BindingPath="Name" />

        
        <z:DataGridTableColumn Header="在职" Width="60"
                               HorizontalContentAlignment="Center">
            <z:DataGridTableColumn.CellTemplate>
                <DataTemplate x:DataType="local:Person">
                    <CheckBox IsChecked="{Binding IsActive}" />
                </DataTemplate>
            </z:DataGridTableColumn.CellTemplate>
        </z:DataGridTableColumn>

        
        <z:DataGridTableColumn Header="操作" Width="80">
            <z:DataGridTableColumn.CellTemplate>
                <DataTemplate x:DataType="local:Person">
                    <Button Content="编辑" Command="{Binding $parent[Window].DataContext.EditCommand}"
                            CommandParameter="{Binding}" />
                </DataTemplate>
            </z:DataGridTableColumn.CellTemplate>
        </z:DataGridTableColumn>
    </z:DataGridTable.Columns>
</z:DataGridTable>

带 CellTemplate 的列默认不可就地编辑(IsEditable 被忽略),交互完全交给模板内的控件。

常用属性
属性 说明 默认
ItemsSource 行数据集合 —
IsReadOnly 全表只读 false
ShowRowNumbers 显示行号列 true
IsStriped 斑马纹 true
IsColumnMenuEnabled 列编辑菜单总开关 false
IsFunctionBarEnabled 顶部功能区 true
IsPaginationEnabled 分页栏 false
IsPreloadEnabled 大数据预加载动画 false
选择状态(可绑定)
  • SelectedRow(TwoWay):当前活动行
  • SelectedColumnIndex(TwoWay):当前活动列,-1 无
  • SelectedCells(OneWayToSource):选中的单元格坐标列表
  • SelectedCellCount、SelectedRowCount:选中数量

事件(在 code-behind 中订阅):

// 双击行:打开详情窗口(只读表也会触发)
table.RowActivated += (s, e) =>
{
    var person = (Person)e.Row;     // e.RowIndex 为行索引
    var detail = new DetailWindow(person);
    _ = detail.ShowDialog((Window)VisualRoot!);
};

// 列宽 / 列序变化:可在此自动保存布局
table.ColumnLayoutChanged += (s, e) => SaveLayout();
顶部功能区与行增删

功能区位于表格顶部,左侧是「+ 新增行」组合按钮与「删除选中」,右侧 FunctionBarSlot 可放任意自定义控件。

「+ 新增行」是一个 ComposeButton,下拉菜单可选择插入位置:

菜单项 说明
放置于选中行之上 InsertLocation.AboveSelected
放置于选中行之下 InsertLocation.BelowSelected
放置于数据末尾 InsertLocation.AtEnd(默认)
插入多行… 弹出对话框,填写行数与位置

控件不直接修改数据源,新增 / 删除通过事件交给业务处理。下面是一个完整的 code-behind 示例:

// PeopleView.axaml.cs
public partial class PeopleView : UserControl
{
    private ObservableCollection<Person> _people = new();

    public PeopleView()
    {
        InitializeComponent();
        var table = this.FindControl<DataGridTable>("PeopleTable")!;

        // 点击主按钮:按当前所选插入位置加一行
        table.RowAddRequested += (s, e) =>
            InsertAt(table.InsertLocation, new Person("新员工", 0, "未指定"));

        // 插入多行对话框确认后:批量加 N 行
        table.RowsAddRequested += (s, e) =>
        {
            for (var i = 0; i < e.Count; i++)
                InsertAt(e.Location, new Person("新员工", 0, "未指定"));
        };

        // 删除选中:e.RowIndices 是页面内行号,倒序删除避免索引错位
        table.RowsDeleteRequested += (s, e) =>
        {
            foreach (var row in e.RowIndices.OrderByDescending(r => r))
                _people.RemoveAt(row);
        };
    }

    // 按插入位置算出目标索引
    private void InsertAt(InsertLocation, Person person)
    {
        var index = location switch
        {
            InsertLocation.AboveSelected => _people.Count,   // 实际项目中取选中行索引
            InsertLocation.BelowSelected => _people.Count,
            _                            => _people.Count,   // AtEnd
        };
        _people.Insert(index, person);
    }
}

无选中行时,「之上 / 之下」自动退化为末尾追加。 开启分页时,事件给的是「当前页内」行号;要映射到全量数据源,需加上偏移量 (PageIndex - 1) * PageSize:

var sourceIndex = (table.PageIndex - 1) * table.PageSize + pageRowIndex;
列编辑菜单

开启 IsColumnMenuEnabled 后,表头出现向下箭头,点击展开菜单:

菜单项 说明
对齐方式 左 / 中 / 右(单选)
允许编辑 切换该列 IsEditable
自动适应列宽 按内容重测本列宽度
按此列筛选… 打开列值筛选对话框
列值筛选

「按此列筛选…」打开卡片式对话框,含搜索框与勾选列表(复选框 / 值 / 数量),底部为清除筛选 / 取消 / 应用筛选。多选标题栏支持全选、部分选、全不选三态。

<z:DataGridTable ItemsSource="{Binding Rows}"
                 ColumnFilters="{Binding Filters}" />

相关 API:GetDistinctColumnValues(col)、ClearColumnFilter(col)、ClearAllFilters()。

分页

开启 IsPaginationEnabled 后,表格底部分页栏显示总行数、选中统计、翻页控件与每页大小设置。表格内部按 PageIndex / PageSize 切片,列宽仍按全量测量,跨页保持稳定。

属性 / 方法 说明
PageIndex 当前页(1-based,双向,默认 1)
PageSize 每页行数(双向,默认 50)
TotalCount 过滤后总行数
PageCount 总页数
GoToFirstPage() / GoToLastPage() 首页 / 末页
GoToPrevPage() / GoToNextPage() 上一页 / 下一页
GoToPage(n) 跳到指定页
PageChanged 事件 翻页或改页大小时触发

每页大小支持 50 / 100 / 500 / 1000 / 自定义(范围 1–100000)。

监听翻页事件:

table.PageChanged += (s, e) =>
{
    Debug.WriteLine($"从第 {e.OldIndex} 页翻到第 {e.NewIndex} 页(每页 {e.PageSize} 行)");
};
保存 / 恢复列布局
var json = JsonSerializer.Serialize(table.SaveColumnLayout());
table.RestoreColumnLayout(JsonSerializer.Deserialize<List<ColumnLayout>>(json));

SaveColumnLayout() 导出列序与宽度(列需设 Id),RestoreColumnLayout() 恢复。订阅 ColumnLayoutChanged 可在用户调整后自动保存(建议防抖)。

预加载

数据量大时开启 IsPreloadEnabled:切到表格先显示加载动画,列宽测量分帧执行并汇报进度,完成后平滑揭示内容。

相关属性:IsLoading、LoadingProgress(0–100,小于 0 为不确定模式)、LoadingText。


ComposeButton

组合按钮:左侧主按钮触发操作,右侧 ▼ 弹出菜单。点 ▼ 只弹菜单,不会触发主按钮的 Click。

<z:ComposeButton x:Name="NewButton" Content="新建"
                 Theme="{StaticResource ComposeButton.Mini.Fill}"
                 Click="OnNewClicked" />

菜单通常在 code-behind 中构建并赋值:

public MyView()
{
    InitializeComponent();

    var menu = new MenuFlyout();
    menu.Items.Add(new MenuItem { Header = "空白文档" });
    var fromTemplate = new MenuItem { Header = "从模板创建…" };
    fromTemplate.Click += (s, e) => OpenTemplatePicker();
    menu.Items.Add(fromTemplate);
    menu.Items.Add(new Separator());
    menu.Items.Add(new MenuItem { Header = "打开…" });

    NewButton.MenuFlyout = menu;
}

private void OnNewClicked(object? sender, RoutedEventArgs e)
{
    // 只有点左侧「新建」主按钮才会执行;点 ▼ 不进入这里
    CreateDocument();
}
成员 说明
Content 主按钮内容(文字 / 图标)
MenuFlyout ▼ 弹出的菜单
ChevronIconPath ▼ 图标资源路径,默认内建,可替换或置 null 隐藏
Click 事件 仅点主按钮时触发

在 XAML 里也可以直接内联菜单:

<z:ComposeButton Content="新建" Click="OnNewClicked">
    <z:ComposeButton.MenuFlyout>
        <MenuFlyout>
            <MenuItem Header="空白文档" />
            <MenuItem Header="打开…" />
        </MenuFlyout>
    </z:ComposeButton.MenuFlyout>
</z:ComposeButton>

RatingControl

星级评分。

<z:RatingControl Value="3" Maximum="5" />
属性 说明
Value 当前评分(双向)
Maximum 星数
IsReadOnly 只读

LoadingRing

圆圈加载动画。


<z:LoadingRing IsIndeterminate="True" />


<z:LoadingRing IsIndeterminate="False" Value="{Binding Percent}" />
属性 说明 默认
IsIndeterminate 是否不确定模式 true
Value 进度值 0
Minimum 最小值 0
Maximum 最大值 100

HexTextBox

十六进制输入框,输入自动按两位空格分组。

<z:HexTextBox RawText="{Binding Hex}" MaxByteCount="16" />
属性 说明
RawText 去除空格的原始值(双向)
MaxByteCount 最大字节数,超出截断

TextLabel

随主题变色的文字控件,用法与 TextBlock 一致。

<z:TextLabel Text="标题" />

主题

ZXUI 基于 Avalonia 官方 FluentTheme,在其上叠加线条风样式。整体视觉语言:

  • 无竖向网格线,仅用细灰分隔线(ZXLineBrush)划分结构
  • 克制的中性灰阶、小圆角(3–6px)
  • 行 hover 极浅高亮(ZXHoverBrush)
  • 柔和投影(ZXCardMenuShadow)让卡片 / 浮层"浮"在画面上

明 / 暗主题各有一套设计令牌,集中在 ZXUI.Themes.Sample/Themes/Tokens.axaml,颜色资源用 DynamicResource 引用,切换即时生效。在应用资源中覆盖同名令牌即可整体定制风格:

<Application.Resources>
    <SolidColorBrush x:Key="ZXCellSelectedLineBrush" Color="#3B6FE0" />
    <x:Double x:Key="ZXTableRowHeight">28</x:Double>
</Application.Resources>

各控件主题变体

主题以 ControlTheme 定义,使用时通过 Theme="{StaticResource 键名}" 选择;不指定时使用类型键({x:Type ...})默认主题。

Button(按钮)
形态 Mini Regular(默认) Large
描边(透明底 + 灰线框) Button.Mini Button(类型键,自动应用) Button.Large
Fill(实心 + 白字,页面主操作) Button.Fill.Mini Button.Fill Button.Fill.Large
Success(绿底白字) Button.Fill.Success.Mini — —
Danger(红底白字) Button.Fill.Danger.Mini — —
Borderless(无框灰字,hover 浮浅底) Button.Mini.Borderless Button.Borderless Button.Borderless.Large

交互特色:所有按钮 hover / pressed 只改变背景色,文字颜色保持不变(Fill 系始终白字);统一 Cursor=Hand、80ms 画刷过渡、按下有轻微缩放。

TextLabel(文字)
主题 特色
类型键(默认) 正文色 ZXTextBrush,Regular 字号
TextLabel.Mini 小字号
TextLabel.Large 大字号
TextLabel.Mini.Light 小字号 + 弱化灰字 ZXTextMutedBrush,适合状态 / 页脚等次要文字
TextBox(输入框)
主题 特色
类型键(默认) 线条风边框,聚焦时边框转 accent
TextBox.Mini 紧凑尺寸
TextBox.Large 大尺寸
ZXCellEditorTextBox 单元格就地编辑专用(无边框,嵌入表格使用)
CheckBox / RadioButton
主题 特色
CheckBox.Mini 14px 紧凑方框,勾选标记按比例缩小,全套 hover / pressed / disabled / 三态配色
CheckBox.Large 大尺寸复选框
RadioButton.Mini 14px 紧凑单选圆点(外圈 + 6px 选中内点),与 mini 表格 / 弹窗风格统一
ComposeButton(组合按钮)
主题 特色
ComposeButton.Split(默认) ▼ 在右:主按钮 → 1px 竖分隔线 → ▼ 按钮,整体 1px 描边
ComposeButton.Split.Left ▼ 在左:▼ 按钮 → 分隔线 → 主按钮
ComposeButton.Mini.Fill accent 蓝底白字胶囊,与 Button.Fill.Mini 等高,用于工具栏主操作

▼ 区域固定 22×22、垂直居中,悬停浮浅底;整体 disabled 时半透。

DataGridTable(表格内嵌视觉)

表格本体的视觉同样由主题部件构成:

  • zx-mini-table(Class):弹窗内值列表专用——去外框 / 网格线、表头浅底色(ZXStripeBrush)、行 hover 浅蓝、字号收到 10px
  • 行号列表头 #、行号单元格:透明底,承担点击选行与拖动重排的命中区
  • 选中单元格:ZXCellSelectedBrush 底色 + 2px ZXCellSelectedLineBrush 外框

主题画廊

Demo 左侧导航的「主题画廊 ThemeGallery 🎨」页:顶部可切换 Light / Dark,主体按控件分区展示所有变体的实际效果,可作为选型对照与自定义主题的参照。

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.21-alpha 38 10/8/2026

- 新增 TextLabel:继承 TextBlock 的专用文字控件,类型键主题提供 Foreground(明暗自动);文字配色收敛到独立类型,不影响 Button 等控件内部的内联 TextBlock,Fill 白字经继承稳定生效;移除原 Window 全局 Foreground Style
- 基础控件不重写模板:Button/TextBox/ComboBox 类型键主题 BasedOn Fluent 同名主题只覆盖颜色/边框,变体(Mini/Large/Fill/Borderless)同样 BasedOn 叠加;CheckBox 仅提供尺寸变体
- 主题画廊新增 TextLabel 展示区;Button 按形态 × 尺寸网格,其余控件一行三尺寸
- 更早:DataGridTable 分页插件、列编辑插件与 CardMenu 卡片菜单