文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

WPF实现自定义一个自删除的多功能ListBox

2022-12-28 09:00

关注

我需要一个ListBox,他在界面上分为几列,每列对应一系列的数据。第一行是各数据的标题,支持横向滚动,竖向只支持数据源滚动,标题不随之滚动。视觉上与ListView类似。支持等比拉伸,支持多选,支持从界面去更改内部数据源,支持子项从ListBox中删除自己。为了实现这些功能,我决定自定义一个特殊的列表,当然他还是继承自ListBox。

1.首先他支持等比拉伸,且数据分列显示。首先想到Grid的ColumnDefinitions可以满足。

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="74*" />
    <ColumnDefinition Width="179*" />
    <ColumnDefinition Width="157*" />
</Grid.ColumnDefinitions>

2.支持从界面去更改内部数据源,支持子项从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中绑定的数据源。

3.我们还需要把这个自定义的ListBoxItem放到我们自定义的ListBox中,让所有子项都应用这个自定义的ListboxItem,而不是默认的ListboxItem。代码如下:

internal class TestListBox : ListBox
{
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new TestItem();
    }
}

4.为了实现数据与标题分离的滚动效果,我单独将标题拿到外部,对标题进行单独显示,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的文章就介绍到这了,更多相关WPF自删除多功能ListBox内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯