WINUI/WPF——自定义ListView

需求概述

首先明确我们要做什么:一个包含4个关注点的配置,每个关注点包含​​名称、颜色、半径、启用状态​​四个可配置属性。所有配置需持久化到数据库,并能实时反馈到UI显示上。

  • ​​核心功能点​​:

    1. 关注点属性动态配置

    2. 配置数据实时生效

    3. 所有数据持久化存储

    4. 优雅、用户友好的交互界面

需求分析

按上述需求,可以通过一个关注点类,将名称、颜色、半径、启用作为它的属性,同时由于名称是可变化的,最好再添加一个别名或ID的属性,以便在数据库中进行存储。

关注点类:名称与颜色的存储,可以使用字符串,半径使用浮点数,是否启用使用bool值。

所有关注点可以形成一个可观察对象的集合,以用于UI上的绑定。

需求实现

UI代码如下,以下为WINUI xaml代码,WPF亦可做参考(仅需极少改动即可):

<?xml version="1.0" encoding="utf-8" ?>
<Window
    x:Class="WINUIDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:converters="using:WINUIDemo.Converters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:WINUIDemo"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewmodels="using:WINUIDemo.ViewModel"
    mc:Ignorable="d">


    <StackPanel>
        <StackPanel.Resources>
            <Style x:Key="FocusPointItemStyle" TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Left" />
                <!--  内容左对齐  -->
                <Setter Property="Padding" Value="10" />
                <!--  内边距  -->
                <Setter Property="Margin" Value="0,0,10,0" />
                <!--  禁止水平拉伸  -->
                <Setter Property="HorizontalAlignment" Value="Left" />
                <Setter Property="Width" Value="Auto" />

                <!--  禁用悬停和选中时的背景变化  -->
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="BorderBrush" Value="Transparent" />

                <!--  修改 VisualStateManager 行为  -->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <Grid
                                x:Name="ContentBorder"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                                <ContentPresenter
                                    x:Name="ContentPresenter"
                                    Margin="{TemplateBinding Padding}"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                    Content="{TemplateBinding Content}"
                                    ContentTemplate="{TemplateBinding ContentTemplate}"
                                    ContentTransitions="{TemplateBinding ContentTransitions}" />
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <DataTemplate x:Key="FocusPointTemplate" x:DataType="viewmodels:FocusPoint">
                <Border
                    Padding="10"
                    Background="{ThemeResource CardBackgroundFillColorDefault}"
                    BorderBrush="AliceBlue"
                    BorderThickness="1"
                    CornerRadius="8">
                    <StackPanel Orientation="Horizontal" Spacing="10">
                        <!--  名称  -->
                        <TextBox
                            Width="100"
                            VerticalAlignment="Center"
                            Text="{x:Bind Name}"
                            TextAlignment="Center" >
                        </TextBox>
                            
                            
                        <!--  颜色选择按钮(默认显示图标)  -->
                        <Button
                            x:Name="ColorPickerButton"
                            Width="32"
                            Height="32"
                            Padding="0">
                            <Button.Content>
                                <!--  小图标:显示当前颜色的方块  -->
                                <Rectangle
                                    Width="20"
                                    Height="20"
                                    Fill="{x:Bind ToBrush(Color), Mode=OneWay}" />
                            </Button.Content>

                            <Button.Flyout>
                                <Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
                                    <!--  展开后的完整ColorPicker  -->
                                    <ColorPicker
                                        Width="320"
                                        Height="320"
                                        ColorSpectrumShape="Ring"
                                        IsAlphaEnabled="False"
                                        IsColorPreviewVisible="False"
                                        Color="{x:Bind Color, Mode=TwoWay}" />
                                </Flyout>
                            </Button.Flyout>
                        </Button>

                        <!--  半径和启用控件  -->
                        <StackPanel VerticalAlignment="Center" Orientation="Horizontal">
                            <TextBlock
                                Margin="0,0,10,0"
                                VerticalAlignment="Center"
                                Text="半径" />
                            <NumberBox
                                Width="50"
                                Header=""
                                Maximum="50"
                                Minimum="1"
                                Value="{x:Bind Radius, Mode=TwoWay}" />
                        </StackPanel>
                        <CheckBox
                            Width="Auto"
                            MinWidth="0"
                            Content="启用"
                            IsChecked="{x:Bind IsEnabled, Mode=TwoWay}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
        </StackPanel.Resources>

        <ListView
            VerticalAlignment="Center"
            HorizontalContentAlignment="Center"
            ItemContainerStyle="{StaticResource FocusPointItemStyle}"
            ItemTemplate="{StaticResource FocusPointTemplate}"
            ItemsSource="{x:Bind viewModel.FocusPoints}"
            Loaded="ListView_Loaded">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <!--<ItemsStackPanel Orientation="Horizontal" />-->
                    <ItemsWrapGrid
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        MaximumRowsOrColumns="2"
                        Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>
    </StackPanel>
</Window>

UI设计亮点​​:

  • ​​集成式颜色选择​​:将ColorPicker嵌入到Flyout中,节省空间,交互优雅。

  • ​​数据绑定​​:所有控件属性均与ViewModel中的数据进行绑定,实现双向更新。

以下为FocusPoint,使用ObservableObject(MVVMToolkit)来实现属性变更通知。

using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI;
using System;
using Windows.UI;

namespace WINUIDemo.ViewModel
{
    // 关注点数据模型
    public partial class FocusPoint : ObservableObject
    {
        private string name;
        private string color;
        private double radius;
        private bool isEnabled;

        public string Name
        {
            get => name;
            set { SetProperty(ref name, value); }
        }

        public string Color
        {
            get => color;
            set { SetProperty(ref color, value); }
        }

        public double Radius
        {
            get => radius;
            set { SetProperty(ref radius, value); }
        }

        public bool IsEnabled
        {
            get => isEnabled;
            set { SetProperty(ref isEnabled, value); }
        }

        public Microsoft.UI.Xaml.Media.SolidColorBrush ToBrush(string color)
        {
            return new Microsoft.UI.Xaml.Media.SolidColorBrush(FromHex(color));
        }
        private static Color FromHex(string hex)
        {
            hex = hex.TrimStart('#');
            byte a = 255; // 默认不透明
            if (hex.Length == 8)
            {
                a = Convert.ToByte(hex.Substring(0, 2), 16);
                hex = hex.Substring(2); // 移除 Alpha 部分
            }
            byte r = Convert.ToByte(hex.Substring(0, 2), 16);
            byte g = Convert.ToByte(hex.Substring(2, 2), 16);
            byte b = Convert.ToByte(hex.Substring(4, 2), 16);
            return ColorHelper.FromArgb(a, r, g, b);
        }
        // 默认值构造函数
        public FocusPoint(string name, string color, double radius, bool isEnabled)
        {
            Name = name;
            Color = color;
            Radius = radius;
            IsEnabled = isEnabled;
        }

    }


}

​设计要点​​:颜色采用Hex字符串存储,便于序列化和数据库存储,同时提供方法与XAML的Brush相互转换。 

以下为VM

using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI;
using System.Collections.ObjectModel;

namespace WINUIDemo.ViewModel
{
    public partial class MainViewModel : ObservableRecipient
    {


        [ObservableProperty]
        public ObservableCollection<FocusPoint> focusPoints;

        public MainViewModel()
        {
            FocusPoints = new ObservableCollection<FocusPoint>
             {
                 new ("关注点1", Colors.Red.ToString(), 10.0, true),
                 new ("关注点2", Colors.Blue.ToString(), 15.0, false),
                 new ("关注点3", Colors.Yellow.ToString(), 15.0, false),
                 new ("关注点4", Colors.Green.ToString(), 15.0, false),
             };
        }

        
    }
}

 仅实现测试效果需要的初始数据,未实现数据保存到数据库。

实现效果

CustomerListview

### WINUI 3 vs WPF: 特点、性能、应用场景对比 #### 特点对比 WINUI 3 提供了一种现代化的设计语言和一组新的控件,这些控件具有流畅的动画效果和平滑的交互体验[^1]。相比之下,WPF 已经存在多年并拥有成熟稳定的架构和支持广泛的第三方库,这使其成为企业级应用的理想选择。 对于开发者而言,在创建新项目时可以利用 WinUI 3 中提供的最新特性如 Fluent Design System 来实现更加美观的应用界面;而如果需要维护现有基于 .NET Framework 的大型桌面应用程序,则可能更适合继续使用 WPF 并通过引入一些 UWP 风格组件来进行渐进式的升级[^2]。 #### 性能表现 就运行效率来说,两者都依赖于 Windows Presentation Foundation (WPF) 或者 Universal Windows Platform (UWP),因此它们之间的差异并不明显。然而,由于 WinUI 3 更加注重图形渲染优化并且采用了 DirectComposition 加速机制,所以在处理复杂视觉特效方面可能会表现出更好的性能优势。 另外值得注意的是,虽然目前关于两者的具体性能测试数据有限,但从理论上讲,WinUI 3 可能在某些场景下具备更高的响应速度与更低资源占用率,这是因为它是专门为现代硬件加速设计而成的新一代 UI 框架之一。 #### 应用场景 当涉及到跨平台支持时,显然 WPF 不适用于移动设备或其他操作系统上的客户端软件开发工作。但是借助 Xamarin.Forms 或 MAUI 等工具集,仍然可以在一定程度上扩展其适用范围至其他环境之外。而对于专注于打造原生 Windows Store Apps 的团队来讲,采用 WinUI 3 将会获得最佳实践指导和技术保障[^3]。 综上所述: | 对比项 | WPF | WinUI 3 | | --- | --- | --- | | **特点** | 成熟稳定, 支持广泛<br>第三方库 | 现代化设计,<br>Fluent Style 控件 | | **优点** | 多年积累的经验,<br>适合企业级应用 | 图形渲染优化,<br>DirectComposition 加速 | | **缺点** | 更新较慢,<br>缺乏部分新特性 | 生态系统相对较小,<br>社区活跃度有待提高 | ```csharp // 示例代码展示如何在不同框架中初始化窗口 // WPF 初始化方式 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } // WinUI 3 初始化方式 using Microsoft.UI.Xaml; namespace MyAppNamespace { sealed partial class App : Application { protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { var window = new MainWindow(); window.Activate(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值