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

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

介绍

我有一种情况,我希望能够将项目添加到列表中,并在列表中移动项目,这似乎是使用a的最简单方法ListBox。我立刻想到了如何以通用的方式做到这一点,然后,也许,可以使用行为来做到这一点。这似乎是一个非常有用的想法。我决定以一种简单的方式为我正在开发的应用程序做这件事,但我想我会创建一个演示项目来探索这个想法。这是结果。

概观

该行为实际上有四个独立的部分,可以在一个类中执行不同的功能:

  • 添加项目
  • 将所选项目向上移动一个位置
  • 将所选项目向下移动一个位置
  • 删除所选项目。

每个函数的代码结构非常相似,只有一些细节不同。

将要检查的代码是Move Up函数的代码。

首先是以下定义DependencyProperty

隐藏   复制代码

public static readonly DependencyProperty MoveItemUpProperty =
    DependencyProperty.RegisterAttached("MoveItemUp",
        typeof(Selector), typeof(ListHelperBehavior),
            new PropertyMetadata(null, OnMoveItemUpChanged));

public static Selector GetMoveItemUp(UIElement uiElement)
{ return (Selector)uiElement.GetValue(MoveItemUpProperty); }

public static void SetMoveItemUp(UIElement uiElement, Selector value)
{ uiElement.SetValue(MoveItemUpProperty, value); }

这用于为包含列表的Selector(或ListBox)控件提供绑定。它用于Button执行动作,在这种情况下是将所选项目向上移动一个位置。对于这个动作的代码需要有机会获得ItemsSourceSelectedIndexSelector控制,首先要真正能够做到移动,第二知道要移动的项目。

对于所有操作,此代码几乎相同,只是Add Item不需要监视SelectionChanged事件Selector,并且Button永远不会禁用。

当此DependencyProperty更改时,将OnMoveUpItemChanged执行事件处理程序。此事件处理程序在DependencyPropertyRegisterAttached方法的FrameworkMetadata参数中指定。

隐藏   复制代码

private static void OnMoveItemUpChanged(DependencyObject d,
    DependencyPropertyChangedEventArgs e)
{
    if (e.OldValue is Selector Selector1)
    {
        Selector1.SelectionChanged -= SetMoveItemUpButtonIsEnabled;
    }
    if (e.NewValue is Selector Selector)
    {
        var Button = CheckForButtonBase(d);
        Button.Click -= MoveItemUpEvent;
        Button.Click += MoveItemUpEvent;
        Selector.SetValue(MoveUpButton, Button);
        Selector.SelectionChanged += SetMoveItemUpButtonIsEnabled;
        SetMoveItemUpButtonIsEnabled(Selector, null);
    }
}

此代码将事件处理程序附加到ButtonClick事件和Selector SelectionChanged事件。为了确保Button在订阅事件之前没有双重订阅Click事件,并且删除SelectionChanged旧事件的事件处理程序Selector(如果存在)。此外,Button它保存在附件DependencyProperty中,Selector以便可以找到它以供SelectionChanged事件处理程序使用。最后,Button通过使用SelectionChanged事件处理程序调整IsEnabled值。

为的保存代码ButtonSelector被下面的私人DependencyProperty从而使Button被启用和禁用,可以发现:

隐藏   复制代码

private static readonly DependencyProperty MoveUpButton =
    DependencyProperty.RegisterAttached("MoveUpButton",
        typeof(ButtonBase), typeof(ListHelperBehavior),
            new PropertyMetadata(null));

Add Item代码不需要监视SelectionChanged事件,因为Button从不禁用它。
的Click事件Button下移功能如下:

隐藏   复制代码

private static void MoveItemUpEvent(object sender, RoutedEventArgs e)
{
    Debug.Assert(sender is ButtonBase);
    var Button = (ButtonBase)sender;
    var Selector = GetMoveItemUp(Button);
    var IList = CheckForIList(Selector);
    var itemNumber = Selector.SelectedIndex;
    var item = IList[itemNumber];
    IList.RemoveAt(itemNumber);
    var type = IList.GetType().GetGenericArguments().Single();
    var castInstance = Convert.ChangeType(item, type);
    IList.Insert(itemNumber - 1, castInstance);
    if (itemNumber == 1) Button.IsEnabled = false;
    Selector.SelectedIndex = itemNumber - 1;
}

sender参数必须强制转换为ButtonBase类型,然后用于获取Selector作为ButtonBase中附加属性保存的控件的值。然后使用它来获取IList绑定到Selector ItemsSource DependencyPropertySelectedItem值和值SelectorIList然后复制所选项目,转换为正确的类型(使用Type类的Reflection GetGenericArgument方法获取类型,然后使用Convert.ChangeType方法将其强制转换),然后从IList(RemoveAt方法)中删除IList)。然后使用该Selector Insert方法插入删除的项目。

接下来检查是否现在是第一个项目,禁用Button它是否为,并且Selector SelectedIndex设置为仍然指向同一个项目。

码几乎是相同的,则删除要简单得多,因为它没有保存已删除的项目,然后将其放回IList

最后,有适当的代码启用或禁用Button取决于是否存在SelectedItemSelectedItem是第一个(用于上)或最后一个项目IList(用于下移)。这是SelectedItemSelector触发事件时调用的事件处理程序:

隐藏   复制代码

private static void SetMoveItemUpButtonIsEnabled(object sender, RoutedEventArgs e)
 {
 <code>    Debug.Assert(sender is Selector);
     var Selector = (Selector)sender;
     var IList = CheckForIList(Selector);
     var itemNumber = Selector.SelectedIndex;
     var Button = (ButtonBase) Selector.GetValue(MoveUpButton);
     Button.IsEnabled = (itemNumber >= 1 && itemNumber < IList.Count);
 }</code>

对于这种需要IList绑定到ItemsSourceSelectedIndex,并需要得到Button保存为一个附加属性在此功能Selector。对于Remove函数,只需要知道if SelectedIndex是否等于-1,这样简单得多。

使用行为

要使用此行为,只需要一个从Selector控件派生的列表控件,Name为此控件关联一个值,并Button为每个应该实现的函数定义一个网站源码。在每一个Button XAML只包括ListHelperBahaviorDependencyProperty它有关联BindingSelector

隐藏   收缩    复制代码

<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ListBox Name="TheList"
             ItemsSource="{Binding List}"
             HorizontalAlignment="Stretch"
             VerticalAlignment="Stretch"  >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="200"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding ItemNumber}"/>
                    <TextBlock Grid.Column="1"
                               Text="{Binding TimeCreated}"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <StackPanel Grid.Row="2"
                Margin="-5 5"
                Orientation="Horizontal"
                HorizontalAlignment="Right">
        <Button Content="Add"
                Width="70"
                Margin="5"
                local:ListHelperBehavior.AddToList="{Binding ElementName=TheList}"/>
        <Button Content="Remove"
                Width="70"
                Margin="5"
                local:ListHelperBehavior.RemoveFromList="{Binding ElementName=TheList}"/>
        <Button Content="Move Up"
                Width="70"
                Margin="5"
                local:ListHelperBehavior.MoveItemUp="{Binding ElementName=TheList}"/>
        <Button Content="Move Down"
                Width="70"
                Margin="5"
         local:ListHelperBehavior.MoveItemDown="{Binding ElementName=TheList}"/>
    </StackPanel>

问题

行为存在一些限制,其中一些可以使用其他代码进行处理。
其中一个问题是行为预期绑定到该类型Selector的类型的IList,这意味着这两个ListObservableCollection可使用,但Array Type不能。这可以编码,但需要Array每次重新创建。

另一个限制是Add只有Type在它IList是一个类时才有效,并且有一个默认的构造函数。

当然另一个限制是它只处理从控件派生的Selector控件。

结论

这是一个非常好的小行为,因为它允许更改列表的顺序,并通过仅将行为添加Button到实现该功能的每个项目来添加或删除项目。在ViewModel中无需任何操作即可提供此功能。

原文地址:https://www.cnblogs.com/lonelyxmas/p/10474496.html

时间: 2024-07-30 06:43:10

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

CephFS提供/添加/删除MDS

部署元数据服务器 每个CephFS文件系统至少需要一个MDS,集群维护者通常会根据需要使用其自动部署工具来启动所需的MDS服务器.推荐使用Rook和ansible(通过ceph-ansible剧本)进行此操作.为了更清晰,我们仍在此处使用systemd命令 MDS的硬件配置 MDS的当前版本是单线程的,大多数MDS活动都需要CPU,包括响应客户机请求.在最强的客户机负载下,MDS使用大约2到3个CPU内核,这是由于其他杂项维护线程协同工作即便如此,仍建议为MDS服务器充分配备具有足够核心的高级C

按钮动态添加删除input

症状: 也就是实现,添加按钮不断添加新的输入框,以及删除按钮. 处方代码: <%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@include file="/context/mytags.jsp"%> <!DO

采用WPF开发截图程序,so easy!

原文:采用WPF开发截图程序,so easy! 前言  QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲,岂不快哉. 再强调一点:工具就是生产力!没有掌握WPF之前,我是不会开发这么一个程序的,如果采用MFC.winform框架,工作量是相当的大,开发出来的效果肯定也比较low.本人用WPF,花了一天的功夫,开发了这个小程序.程序的定位就功能简单,平时工

iOS开发项目篇—04添加导航栏的按钮

iOS开发项目篇—04添加导航栏的按钮 一.设置导航栏的按钮 要求实现的效果:             说明:默认状态下和高亮状态下的图片是不一样的. 按钮的图片需要设置默认状态和高亮状态时的显示,系统了提供的下面方法 viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem alloc]initWithImage:<#(UIImage *)#> style:<#(UIBarButtonItemStyle)#>

【iOS开发-76】Private Contacts案例:导航控制器使用、数据传递、第三方类库使用、tableViewCell的添加删除、数据存储等

(1)效果 (2)源代码与第三方类库下载 http://download.csdn.net/detail/wsb200514/8155979 (3)总结 --导航控制器,可以直接用代码的push和pop来控制控制器之间的跳转.也可以使用storyboard的segue来:这里又涉及2种,一种是直接用按钮拖拽到另一个控制器形成segue,这种segue不可拦截,如果点击直接跳转.另一种是从一个控制器拖拽到另一个控制器形成的segue,这种segue没有明确的点击谁来跳转,所以有一个performS

输入框内置按钮标签可删除添加

未添加之前 点击输入框后弹出选项选择后点击确定出现如下页面 添加之后,输入框显示不下的按钮显示省略号 删除一个过后输入框可以显示全就删除省略号按钮 好了大概就这样的下面是git地址:https://gitee.com/hejie1996/InputButton.git 原文地址:https://www.cnblogs.com/hjieone/p/11139799.html

为WPF和Silverlight的Grid添加边框线(zz)

  Grid是WPF和Silverlight中的一个重要的布局元素,其他的布局元素还有StackPanel, Canvas, Border等等.从字面上说,Grid是一个表格的意思,它的使用也确实很方便,从视觉上很像一个表格的样式,有行,有列的概念,这种效果很适合于需要多多个子控件进行布局,并希望保持左边或者上对齐的效果. 我们来看一个最简单的例子(本文采用Silverlight做演示,在WPF中也是一样的) 使用Grid的时候,一般先定义Grid的行和列的设置,然后在其放置其他控件并且设置他们

MFC 基础知识:对话框背景添加图片和按钮Button添加图片

很长时间没有接触MFC相关的知识了,我大概是在大二时候学习的MFC相关知识及图像处理,现在由于要帮个朋友完成个基于C++的程序,所以又回顾了下相关知识.的确,任何知识一段时间过后都比较容易忘记,但回顾起来还是很有印象的. 这篇文章主要是回顾以前的MFC基础知识,给对话框添加背景图片和给按钮button添加背景图片:希望此篇基础性文章对大家有所帮助!同时为下次做MFC相关知识提供点此时所想所感吧.内容比较简单,高手飘过~ 一. 对话框背景添加图片 首先通过VS2012创建MFC对话框应用程序,项目

Stimulsoft Reports.Wpf是针对WPF开发的报表工具控件

Stimulsoft Reports.Wpf是针对WPF开发的报表工具控件.无需上网,所有的WPF功能都能用上!丰富的界面更换功能.查看功能.打印以及导出报表功能——所有的这一切就是它都能轻松实现. 创建Stimulsoft Reports.Wpf是基于Stimulsoft团队多年开发以及使用的报表引擎来创建报表.只需简单的几行代码即可执行报表复杂的操作,报表引擎提供了创建报表的许多功能.大量的组件开发包,独特的一套属性和参数,精心构思的报表体系.很多选项都是绝对独特且仅出现该产品中.Stimu