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

时间:2023-01-07 22:10:03

介绍

我有一种情况,我希望能够将项目添加到列表中,并在列表中移动项目,这似乎是使用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

隐藏   收缩 WPF开发为按钮提供添加,删除和重新排列ListBox内容的功能   复制代码
<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>

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

问题

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

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

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

结论

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

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

  1. 脚本添加删除nginx配置中的内容

    [root@nodejs script]# more editnginx.sh #!/bin/bash # function back_check(){ # 备份配置和覆盖配置文件 cp -rf /e ...

  2. DHTMLX 前端框架 建立你的一个应用程序 教程&lpar;十一&rpar;--添加&sol;删除表格中的记录

    添加/删除表格中的记录 我们的最终功能是在表格中添加删除 我们通过单机工具栏上的按钮来实现添加删除 当我们单击添加按钮的时候, 表单中 第一行默认填写New contact 光标自动聚焦 当用户点击删 ...

  3. C&num;通过Ado&period;net对连接数据库并进行添加删除等常规操作的代码

    如下资料是关于C#通过Ado.net对连接数据库并进行添加删除等常规操作的内容. static string sqlcon = "server=.;database=;Integrated ...

  4. 【WPF开发备忘】使用MVVM模式开发中列表控件内的按钮事件无法触发解决方法

    实际使用MVVM进行WPF开发的时候,可能会用到列表控件中每行一个编辑或删除按钮,这时直接去绑定,发现无法响应: <DataGridTemplateColumn Header="操作& ...

  5. WPF实用指南一:在WPF窗体的边框中添加搜索框和按钮

    原文:WPF实用指南一:在WPF窗体的边框中添加搜索框和按钮 在边框中加入一些元素,在应用程序的界面设计中,已经开始流行起来.特别是在浏览器(Crome,IE,Firefox,Opera)中都有应用. ...

  6. WPF下的Richtextbox中实现表格合并,添加删除行列等功能

    .Net中已有现在的方法实现这些功能,不过可能是由于未完善,未把方法公开出来.只能用反射的方法去调用它. 详细信息可以查看.Net Framework 的源代码 http://referencesou ...

  7. C&num;&sol;AutoCAD 2018&sol;ObjectArx&sol;二次开发添加删除实体的工具函数&lpar;四&rpar;

    1.添加删除实体 C# ObjectARX二次开发添加删除实体是非常容易主要代码如下: 添加实体: objId = btr.AppendEntity(entity); trans.AddNewlyCr ...

  8. arcgis js4&period;x在geojson数据上点击显示弹窗,并添加删除按钮

    实例geojsonLayer时添加属性popupTemplate popupTemplate: { title: action, content: '点击了' } 设置title用于查询到多个grap ...

  9. Swift开发小技巧--TabBar中间按钮的添加方案

    TabBar中间按钮的添加方案 之前做百思项目的时候,也有一个中间按钮,当时是重写的TabBar,这里介绍一个新的方法 给TabbarVC多添加添加一个控制器,这个控制器的作用仅仅是用来占位的,多了这 ...

随机推荐

  1. SA&colon; 情感分析资源(Corpus、Dictionary)

    先主要摘自一篇中文Survey,http://wenku.baidu.com/view/0c33af946bec0975f465e277.html   4.2 情感分析的资源建设 4.2.1 情感分析 ...

  2. Linux 网络编程一(TCP&sol;IP协议)

    以前我们讲过进程间通信,通过进程间通信可以实现同一台计算机上不同的进程之间通信. 通过网络编程可以实现在网络中的各个计算机之间的通信. 进程能够使用套接字实现和其他进程或者其他计算机通信. 同样的套接 ...

  3. &lbrack;物理学与PDEs&rsqb;第3章习题参考解答

    [物理学与PDEs]第3章习题1 只有一个非零分量的磁场 [物理学与PDEs]第3章习题2 仅受重力作用的定常不可压流理想流体沿沿流线的一个守恒量 [物理学与PDEs]第3章习题3电磁场的矢势在 Lo ...

  4. greenplum学习

    公司TM蛋疼,动不动让你学习新东西,就是不让你闲下来,本着胳膊拧不过大腿定律,忍了,这是背景. 好吧哥端起一本厚厚的<GreenPlum企业应用实战>,打开百度开始GP的学习之路: GP只 ...

  5. WIN7下制作的ubunbu U盘安装无法使用

    想在电脑上装个ubuntu 12.04来个双系统.就在win7下用U盘制作了个安装程序.但是U盘启动安装后一直无法开始安装.网上找了大半天才有个结论解决了. 步骤如下: 去ubuntu官网下载安装的i ...

  6. iscc2016-好长的字符串

    Vm0wd2QyVkhVWGhVYmxKV1YwZDRXRmxVUm5kVlJscHpXa2M1VjFKdGVGWlZNbmhQWVd4YWMxZHViRmROYWxaeVdWZDRZV014WkhG ...

  7. Django发送带图片和附件的邮件

    最近需要做集团的SRC系统.暂无安全研发,所以只能找我这个小菜兼职开发.系统使用Django框架,在整个过程中,有许多奇特的需求.在某项需求中,需要给厂商用户发送富文本邮件,漏洞详情,这个折腾了一下, ...

  8. JavaWeb(四)JDBC操作Oracle

    JDBC:Java DataBase Connectivity(java数据库连接) SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC. jdbc是一套标准, ...

  9. 关于python词典(Dictionary)的get&lpar;&rpar;用法

    先贴出参考链接:http://www.runoob.com/python/att-dictionary-get.html get()方法语法: dict.get(key, default=None) ...

  10. firefox 屏蔽Backspace按键的后退功能

    直接上图