原文地址 https://www.cnblogs.com/younShieh/p/17008534.html

如果本文对你有所帮助,不妨点个关注和推荐呀,这是对笔者最大的支持~

我需要一个ListBox,他在界面上分为几列,每列对应一系列的数据。第一行是各数据的标题,支持横向滚动,竖向只支持数据源滚动,标题不随之滚动。视觉上与ListView类似。支持等比拉伸,支持多选,支持从界面去更改内部数据源,支持子项从ListBox中删除自己。为了实现这些功能,我决定自定义一个特殊的列表,当然他还是继承自ListBox。
  1. 首先他支持等比拉伸,且数据分列显示。首先想到Grid的ColumnDefinitions可以满足。
<Grid.ColumnDefinitions>
<ColumnDefinition Width="74*" />
<ColumnDefinition Width="179*" />
<ColumnDefinition Width="157*" />
</Grid.ColumnDefinitions>
  1. 支持从界面去更改内部数据源,支持子项从ListBox中删除自己。

    为了从界面上满足功能,需要重写ItemContainerStyle样式,绘制出该子项Style。在Style中为了处理事件响应,可以通过在数据源子项中增加Command来对对应事件进行处理。但是处理逻辑可能有点繁杂,而且单从数据处理而言,子项无法从父项中删除自己,只能通过视觉树获取父ListBox,实现该功能。这样写的话代码耦合性会有点高,且数据处理时会调取界面处理。我希望数据源内部只是在处理数据,只能通过界面自上而下的访问数据源,而不是数据源和界面都有循环调用。

    第二种方法,我直接重写一个控件继承自ListBoxItem,将之前重写ItemContainerStyle样式复制到该控件前台,并在后台代码中对相应事件进行处理。代码如下:
public partial class TestItem : ListBoxItem
{
public TestItem()
{
InitializeComponent();
} private void Delete_Click(object sender, RoutedEventArgs e)
{
}
}
因为我是继承自ListBoxItem的,所以可以通过
ItemsControl.ItemsControlFromItemContainer(this) is ListBox listBox
方法获取到父listbox的对象,获取到父对象后,就可以从ListBox中删除自己。或是更改ListBox中绑定的数据源。
  1. 我们还需要把这个自定义的ListBoxItem放到我们自定义的ListBox中,让所有子项都应用这个自定义的ListboxItem,而不是默认的ListboxItem。代码如下:
internal class TestListBox : ListBox
{
protected override DependencyObject GetContainerForItemOverride()
{
return new TestItem();
}
}
  1. 为了实现数据与标题分离的滚动效果,我单独将标题拿到外部,对标题进行单独显示,Listbox只显示数据。外部滑动条支持整体横向滑动,Listbox内部滑动条支持内部竖向滑动。给两个滑动条都加上最小宽度。
<ScrollViewer
Grid.Row="1"
Margin="0,20,0,0"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled">
<Border
MinWidth="{Binding MinWidth, ElementName=listbox}"
BorderBrush="#DFDFDF"
BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="52" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="79*" />
<ColumnDefinition Width="104*" />
<ColumnDefinition Width="80*" />
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="20" Background="#F2F2F2" />
<TextBlock Text="ID" />
<TextBlock Grid.Column="1" Text="编号" />
<TextBlock Grid.Column="2" Text="操作" />
<controls:TestListBox
x:Name="listbox"
Grid.Row="1"
Grid.ColumnSpan="3"
MinWidth="1100"
ItemsSource="{Binding ItemsSourceData}"
Style="{StaticResource BaseListBoxStyle.WithOutHorizontalScrollViewer}" />
</Grid>
</Border>
</ScrollViewer>
在Listbox的样式中取消了横向滑动条的显示。
 <Style x:Key="BaseListBoxStyle.WithOutScrollViewer" TargetType="ListBox">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="ScrollViewer.CanContentScroll" Value="False" />
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<ScrollViewer
Focusable="false"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsPresenter Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

【WPF】自定义一个自删除的多功能ListBox的更多相关文章

  1. C语言:自定义一个查找字串的功能函数,类似于<string.h>中的strstr()

    //自定义一个字符串字串查找标准库函数strstr() #include<stdio.h> #include<string.h> char* myStrstr(char *st ...

  2. WPF 自定义一个控件,当点击按钮是触发到ViewModel(业务逻辑部分)和Xaml路由事件(页面逻辑部分)

    #region - 用于绑定ViewModel部分 - public ICommand Command { get { return (ICommand)GetValue(CommandPropert ...

  3. JSTL,自定义一个标签的功能案例

    1.自定义一个带有两个属性的标签<max>,用于计算并输出两个数的最大值: 2.自定义一个带有一个属性的标签<lxn:readFile  src=“”>,用于输出指定文件的内容 ...

  4. WPF开发为按钮提供添加,删除和重新排列ListBox内容的功能

    介绍 我有一种情况,我希望能够将项目添加到列表中,并在列表中移动项目,这似乎是使用a的最简单方法ListBox.我立刻想到了如何以通用的方式做到这一点,然后,也许,可以使用行为来做到这一点.这似乎是一 ...

  5. [WPF 自定义控件]自定义一个“传统”的 Validation.ErrorTemplate

    1. 什么是Validaion.ErrorTemplate 数据绑定模型允许您将与您Binding的对象相关联ValidationRules. 如果用户输入的值无效,你可能希望在应用程序 用户界面 ( ...

  6. wpf 自定义窗口,最大化时不覆盖任务栏

    相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 WindowState="Maximized& ...

  7. [WPF]ListView点击列头排序功能实现

    [转]   [WPF]ListView点击列头排序功能实现 这是一个非常常见的功能,要求也很简单,在Column Header上显示一个小三角表示表示现在是在哪个Header上的正序还是倒序就可以了. ...

  8. WPF 自定义 MessageBox (相对完善版)

    WPF 自定义 MessageBox (相对完善版)     基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...

  9. WPF自定义路由事件(二)

    WPF中的路由事件 as U know,和以前Windows消息事件区别不再多讲,这篇博文中,将首先回顾下WPF内置的路由事件的用法,然后在此基础上自定义一个路由事件. 1.WPF内置路由事件 WPF ...

  10. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

随机推荐

  1. Springboot 之 Mybatis-plus 多数据源

    简介 Mybatis-puls 多数据源的使用,采用的是官方提供的dynamic-datasource-spring-boot-starter包的 @DS 注解,具体可以参考官网: https://g ...

  2. pycharm下载与使用

    pycharm下载与使用 PyCharm是一种Python IDE(Integrated Development Environment,集成开发环境),带有一整套可以帮助用户在使用Python语言开 ...

  3. 内存映射IO(MMIO)

    端口I/O 介绍: 一种I/O编址方式是端口映射I/O(port-mapped I/O), CPU使用专门的I/O指令对设备进行访问, 并把设备的地址称作端口号. 在执行其中的一条指令时,CPU使用地 ...

  4. Flutter Cocoon 已达到 SLSA 2 级标准的要求

    文/ Jesse Seales, Dart 和 Flutter 安全工作组工程师 今年年初,我们发布了 Flutter 2022 产品路线图,其中「基础设施建设」这部分提到:2022 年 Flutte ...

  5. Hive 自定义UDF操作步骤

    Hive 自定义UDF操作步骤 需要自定义类,然后继承UDF 然后在方法envluate()方法里面实现具体的业务逻辑,打包上传到linux(以免出错打包成RunningJar) 一.创建临时函数 ( ...

  6. Linux系统管理_软件管理

    RPM命令 #管理.rpm文件 #RPM包软件命名规则:name-version-releases.arch.rpm rpm -ivh pkgname #安装软件包 rpm -ivh --test p ...

  7. RE语法

    RE,英文为Regular Expression,中文译作正则表达式.用于文本过滤的工具.RE语法由一些元字符.其它任意字符串作为基本单元,匹配次数.分组匹配.锚定符等为操作单元组成.进行逐行扫描,满 ...

  8. 数据结构中的哈希表(java实现)利用哈希表实现学生信息的存储

    哈希表 解释 哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方 内存结构分析图 1.定义一个类为结点,存储的信息 2.定义链表的相关操作 3.定义一个数组存 ...

  9. 深入浅出redis缓存应用

    0.1.索引 https://blog.waterflow.link/articles/1663169309611 1.只读缓存 只读缓存的流程是这样的: 当查询请求过来时,先从redis中查询数据, ...

  10. 25.自定义mixin和基类

    很多时候业务需求并不是几个简单的mixin就可以满足,需要我们自定义mixin # get_object源码中字段查询源代码 filter_kwargs = {self.lookup_field: s ...