WPF——自定义ListBox

在阅读本文前,最好先看看WPF——自定义RadioButton

背景

WPF中实现单选功能通常有两种方案:
- RadioButton组:传统方案,但代码冗余
- ListBox定制:通过样式改造,兼顾数据绑定和UI灵活性

需求

一组选项中,选中某个选项(选项需要横向排列,同时选中效果与未选中效果要能明确显示),就将这个选项的值写入到后端。

设计选型

RadioButton方案

通过RadioButton来实现,是肯定可行的,

但是对于一组RadioButton,需要设置组名;

同时每个RadioButton在Checked时都要触发事件,也需要为它们设置相应的事件,不利于后台绑定:也就是说要将选中值写入VM比较麻烦,因为所有的都需要实现;

并且还存在一个问题,所有RadioButton需要手动去设置相应的显示内容,不能使用一个集合以便于管理。

ListBox方案

通过ListBox也是可行的,只是它就需要进行一些改造了,因为ListBox默认的是纵向排列,同时它没有一个明确的选中与未选中效果;

但是它可以绑定集合,同时通过自定义,可以比较轻松的将选中值写入到VM中;或者通过item的选中事件即可将选中值写入到VM中。

方案对比

方案代码量数据绑定布局灵活性维护成本
RadioButton组困难
ListBox定制简单
 

后续基于ListBox进行实现。

实现

样式定义

 <Style x:Key="RadioListBoxStyle" TargetType="{x:Type ListBox}"><!--  基础样式继承原有ListBoxStyle1  --><Setter Property="Background" Value="{StaticResource ListBox.Static.Background}" /><Setter Property="BorderBrush" Value="{StaticResource ListBox.Static.Border}" /><Setter Property="BorderThickness" Value="1" /><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /><Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" /><Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" /><Setter Property="ScrollViewer.CanContentScroll" Value="true" /><Setter Property="ScrollViewer.PanningMode" Value="Both" /><Setter Property="Stylus.IsFlicksEnabled" Value="False" /><Setter Property="VerticalContentAlignment" Value="Center" /><!--  关键修改1:禁用默认选中效果  --><Setter Property="ItemContainerStyle"><Setter.Value><Style TargetType="{x:Type ListBoxItem}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBoxItem}"><Border Background="Transparent"><ContentPresenter /></Border></ControlTemplate></Setter.Value></Setter></Style></Setter.Value></Setter><!--  ItemsPanel为水平布局  --><Setter Property="ItemsPanel"><Setter.Value><ItemsPanelTemplate>  <!--  改为水平排列  --><StackPanel Orientation="Horizontal" /></ItemsPanelTemplate></Setter.Value></Setter><!--  自定义ItemTemplate模拟RadioButton  --><Setter Property="ItemTemplate"><Setter.Value><DataTemplate><DockPanel LastChildFill="True"><!--  RadioButton部分  --><RadioButtonMargin="5,0,10,0"VerticalAlignment="Center"DockPanel.Dock="Left"Focusable="False"IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" /><!--  文本部分  --><TextBlockMargin="0,0,5,0"VerticalAlignment="Center"Text="{Binding}" /></DockPanel></DataTemplate></Setter.Value></Setter><!--  模板  --><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBox}"><Borderx:Name="Bd"Padding="1"Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"SnapsToDevicePixels="true"><ScrollViewer Padding="{TemplateBinding Padding}" Focusable="false"><ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /></ScrollViewer></Border><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="false"><Setter TargetName="Bd" Property="Background" Value="{StaticResource ListBox.Disabled.Background}" /><Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource ListBox.Disabled.Border}" /></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="IsGrouping" Value="true" /><Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false" /></MultiTrigger.Conditions><Setter Property="ScrollViewer.CanContentScroll" Value="false" /></MultiTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

数据绑定

    <Window.DataContext><local:Tests /></Window.DataContext>

Tests如下,以下可以根据需要自行实现通知属性。

public class Tests:INotifyPropertyChanged
{readonly List<string> testDatas = ["test0","test1","test2","test3","test4",];private string _selectedValue;public string SelectedValue{get => _selectedValue;set { _selectedValue = value; OnPropertyChanged(); }}public List<string> TestDatas { get; set; }public Tests(){TestDatas = testDatas;}//INotifyPropertyChanged实现
}

ListBox如下:

<ListBoxMargin="0,183,462,192"ItemsSource="{Binding TestDatas}"SelectedItem="{Binding SelectedValue, Mode=TwoWay}"Style="{DynamicResource RadioListBoxStyle}" />

效果展示

图:横向排列的单选ListBox,左侧为RadioButton,右侧为文本

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/89983.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rancher上使用rke在华为云多网卡的服务器上安装k8s集群问题处理了

报错:问题&#xff1a;[[network] Host [192.168.0.213] is not able to connect to the following ports: [192.168.0.213:2379]. Please check network policies and firewall rules]问题&#xff1a; roothwy-isms-210-66:~# gotelnet 172.17.210.66 2379 map[2379:failed] …

xformers包介绍及代码示例

文章目录主要特性安装方式主要优势使用场景注意事项代码示例xFormers是由Meta开发的一个高性能深度学习库&#xff0c;专门用于优化Transformer架构中的注意力机制和其他组件。它提供了内存高效和计算高效的实现&#xff0c;特别适用于处理长序列和大规模模型。github地址&…

CityEngine自动化建模

CityEngine学习记录 学习网址&#xff1a; 百度安全验证 CityEngine-CityEngine_Rule-based_Modeling-基于规则建模和输出模型 - 豆丁网 CityEngine 初探-CSDN博客 City Engine CGA 规则包_cga规则-CSDN博客 CityEngine学习记录 学习网址&#xff1a;百度安全验证 CityE…

Nacos+LoadBalancer实现服务注册与发现

目录 一、相关文章 二、兼容说明 三、服务注册到Nacos 四、服务发现 五、服务分级存储模型 六、查看集群服务 七、LoadBalancer负载均衡 一、相关文章 基础工程&#xff1a;gradle7.6.1springboot3.2.4创建微服务工程-CSDN博客 Nacos服务端安装&#xff1a;Nacos服务端…

事务并发-封锁协议

事务并发数据库里面操作的是事务。事务特性&#xff1a;原子性&#xff1a;要么全做&#xff0c;要么不做。一致性&#xff1a;事务发生后数据是一致的。隔离性&#xff1a;任一事务的更新操作直到其成功提交的整个过程对其他事务都是不可见的&#xff0c;不同事务之间是隔离的…

大气波导数值预报方法全解析:理论基础、预报模型与误差来源

我们希望能够像天气预报一样&#xff0c;准确预测何时、何地会出现大气波导&#xff0c;其覆盖范围有多大、持续时间有多长&#xff0c;以便为通信、雷达等应用提供可靠的环境保障。 目录 &#xff08;一&#xff09;气象预报 1.1 气象预报的分类 1.2 大气数值预报基础 1.2…

关于JavaWeb的总结笔记

JavaWeb基础描述Web服务器的作用是接受客户端的请求&#xff0c;给客户端响应服务器的使用Tomcat&#xff08;最常用的&#xff09;JBossWeblogicWebsphereJavaWeb的三大组件Servlet主要负责接收并处理来自客户端的请求&#xff0c;随后生成响应结果。例如&#xff0c;在处理用…

生成式引擎优化(GEO)核心解析:下一代搜索技术的演进与落地策略

最新统计数据声称&#xff0c;今天的 Google 搜索量是 ChatGPT 搜索的 373 倍&#xff0c;但我们大多数人都觉得情况恰恰相反。 那是因为很多人不再点击了。他们在问。 他们不是浏览搜索结果&#xff0c;而是从 ChatGPT、Claude 和 Perfasciity 等工具获得即时的对话式答案。这…

网编数据库小练习

搭建服务器客户端&#xff0c;要求 服务器使用 epoll 模型 客户端使用多线程 服务器打开数据库&#xff0c;表单格式如下 name text primary key pswd text not null 客户端做一个简单的界面&#xff1a;1&#xff1a;注册2&#xff1a;登录无论注册还是登录&#xff0c;…

理解 PS1/PROMPT 及 macOS iTerm2 + zsh 终端配置优化指南

终端提示符&#xff08;Prompt&#xff09;是我们在命令行中与 shell 交互的关键界面&#xff0c;它不仅影响工作效率&#xff0c;也影响终端显示的稳定和美观。本文将结合 macOS 上最流行的 iTerm2 终端和 zsh shell&#xff0c;讲解 PS1/PROMPT 的核心概念、常见配置技巧&…

Laravel 原子锁概念讲解

引言 什么是竞争条件 (Race Condition)&#xff1f; 在并发编程中&#xff0c;当多个进程或线程同时访问和修改同一个共享资源时&#xff0c;最终结果会因其执行时序的微小差异而变得不可预测&#xff0c;甚至产生错误。这种情况被称为“竞争条件”。 例子1&#xff1a;定时…

83、形式化方法

形式化方法&#xff08;Formal Methods&#xff09; 是基于严格数学基础&#xff0c;通过数学逻辑证明对计算机软硬件系统进行建模、规约、分析、推理和验证的技术&#xff0c;旨在保证系统的正确性、安全性和可靠性。以下从核心思想、关键技术、应用场景、优势与挑战四个维度展…

解决 Ant Design v5.26.5 与 React 19.0.0 的兼容性问题

#目前 Ant Design v5.x 官方尚未正式支持 React 19&#xff08;截至我的知识截止日期2023年10月&#xff09;&#xff0c;但你仍可以通过以下方法解决兼容性问题&#xff1a; 1. 临时解决方案&#xff08;推荐&#xff09; 方法1&#xff1a;使用 --legacy-peer-deps 安装 n…

算法与数据结构(课堂2)

排序与选择 算法排序分类 基于比较的排序算法&#xff1a; 交换排序 冒泡排序快速排序 插入排序 直接插入排序二分插入排序Shell排序 选择排序 简单选择排序堆排序 合并排序 基于数字和地址计算的排序方法 计数排序桶排序基数排序 简单排序算法 冒泡排序 void sort(Item a[],i…

跨端分栏布局:从手机到Pad的优雅切换

在 UniApp X 的世界里&#xff0c;我们常常需要解决一个现实问题&#xff1a; “手机上是全屏列表页&#xff0c;Pad上却要左右分栏”。这时候&#xff0c;很多人会想到 leftWindow 或 rightWindow。但别急——这些方案 仅限 Web 端&#xff0c;如果你的应用需要跨平台&#xf…

华为服务器管理工具(Intelligent Platform Management Interface)

一、核心功能与技术架构 硬件级监控与控制 全维度传感器管理:实时监测 CPU、内存、硬盘、风扇、电源等硬件组件的温度、电压、转速等参数,支持超过 200 种传感器类型。例如,通过 IPMI 命令ipmitool sdr elist可快速获取服务器传感器状态,并通过正则表达式提取关键指标。 远…

Node.js Express keep-alive 超时时间设置

背景介绍随着 Web 应用并发量不断攀升&#xff0c;长连接&#xff08;keep-alive&#xff09;策略已经成为提升性能和资源复用的重要手段。本文将从原理、默认值、优化实践以及潜在风险等方面&#xff0c;全面剖析如何在 Node.js&#xff08;Express&#xff09;中正确设置和应…

学习C++、QT---30(QT库中如何自定义控件(自定义按钮)讲解)

每日一言你比想象中更有韧性&#xff0c;那些看似艰难的日子&#xff0c;终将成为勋章。自定义按钮我们要知道自定义控件就需要我们创建一个新的类加上继承父类&#xff0c;但是我们还要注意一个点&#xff0c;就是如果我们是自己重头开始造控件的话&#xff0c;那么我们就直接…

【补充】Linux内核链表机制

专题文章&#xff1a;Linux内核链表与Pinctrl数据结构解析 目标&#xff1a; 深入解析Pinctrl子系统中&#xff0c;struct pinctrl如何通过内核链表&#xff0c;来组织和管理其多个struct pinctrl_state。 1. 问题背景&#xff1a;一个设备&#xff0c;多种引脚状态 一个复杂的…

本地部署Dify、Docker重装

需要先安装一个Docker&#xff0c;Docker就像是一个容器&#xff0c;将部署Dify的空间与本地环境隔离&#xff0c;避免因为本地环境的一些问题导致BUG。也确保了环境的统一&#xff0c;不会出现在自己的电脑上能跑但是移植到别人电脑上就跑不通的情况。那么现在就开始先安装Doc…