在WPF中的ItemsControl中使用事件和命令(Using events and Commands within ItemsControl in WPF)
Say I have a standard WPF ItemsControl bound to an ObservableCollection of "Dog" objects like so:
<ItemsControl ItemsSource="{Binding Dogs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Breed}"/>
<TextBlock Text="{Binding Weight}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I want the user to be able delete any of the dogs in the collection. In the past I've been doing this with a ListBox control and binding my ViewModel to the SelectedItem property. I then create a button with an event that removes the selected object from the ObservableCollection.
This works OK but I'd like to lay it out so each row can have its own delete button.
<ItemsControl ItemsSource="{Binding Dogs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Breed}"/>
<TextBlock Text="{Binding Weight}"/>
<Button Click="Click_EventHandler"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And an event that looks like this:
private void ListBox_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Delete this Dog Object from Observable Collection
}
Shoving a button into the ItemTemplate and giving it an event crashes WPF, and binding a command to a button within an ItemTemplate doesn't do anything at all so my former method will not work.
The only way I can think of doing this is adding a ToggleButton to the ItemTemplate and binding to the View Model, and then firing an event in the Setter. Not exactly an elegant solution.
Anyone have any better idea on how to go about this?
You can bind commands like everything else, but first you need your implementation of ICommand interface, something like this:
public class RelayCommand: ICommand
{
private Action<object> _execute;
private Predicate<object> _canExecute; public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
} public RelayCommand(Action<object> execute) : this(execute, null) { } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter)
{
return _canExecute != null ? _canExecute(parameter) : true;
} public void Execute(object parameter)
{
if (CanExecute(parameter) && _execute != null) _execute(parameter);
}
}
and then your Dog class needs to expose for example ICommand DeleteCmd property:
class Dog
{
...
private RelayCommand _deleteCmd; private void DoDelete(object parameter)
{
//put delete action here
} public ICommand DeleteCmd
{
get
{
if (_deleteCmd == null) _deleteCmd = new RelayCommand(o => DoDelete(o));
return _deleteCmd;
}
}
}
and then you bind it like this:
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Breed}"/>
<TextBlock Text="{Binding Weight}"/>
<Button Command="{Binding DeleteCmd}"/>
</StackPanel>
说我有一个标准的WPF ItemsControl绑定到一个ObservableCollection的"狗"对象像这样:
< ItemsControl ItemsSource ="{绑定狗}">
< ItemsControl.ItemTemplate>
< DataTemplate>
< StackPanel Orientation ="Horizontal">
< TextBlock Text ="{Binding Name}"/>
< TextBlock Text ="{Binding Breed}"/>
< TextBlock Text ="{Binding Weight}"/>
< / StackPanel>
< / DataTemplate>
< /ItemsControl.ItemTemplate>
< / ItemsControl>
我希望用户能够删除集合中的任何狗。过去我一直在使用ListBox控件,并将ViewModel绑定到SelectedItem属性。然后,我创建一个带有事件的按钮,从ObservableCollection中删除所选对象。
这样可以正常工作,但是我想排除它,所以每一行都可以自己的删除按钮。
< ItemsControl ItemsSource ="{Binding Dogs}">
< ItemsControl.ItemTemplate>
< DataTemplate>
< StackPanel Orientation ="Horizontal">
< TextBlock Text ="{Binding Name}"/>
< TextBlock Text ="{Binding Breed}"/>
< TextBlock Text ="{Binding Weight}"/>
< Button Click ="Click_EventHandler"/>
< / StackPanel>
< / DataTemplate>
< /ItemsControl.ItemTemplate>
< / ItemsControl>
另外一个类似这样的事件:
< pre> private void ListBox_PreviewMouseDown(object sender,System.Windows.Input.MouseButtonEventArgs e)
{
//从可观察集合中删除此Dog对象
}
将一个按钮放入ItemTemplate并给它一个事件崩溃WPF,并将命令绑定到一个按钮在ItemTemplate中没有任何东西,所以我以前的方法将无法正常工作。
我可以想到这样做的唯一方法是将一个ToggleButton添加到ItemTemplate,绑定到视图模型,然后在Setter中触发一个事件。不完全是一个优雅的解决方案。
任何人都有更好的想法如何去做这个?
您可以像其他一样绑定命令,但首先需要实现 ICommand 界面,如下所示:
public class RelayCommand:ICommand
{
private Action< object> _执行;
private Predicate< object> _canExecute;
public RelayCommand(Action< object> execute,Predicate< object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action< object> execute):this(execute,null){}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute!= null? _canExecute(参数):true;
}
public void Execute(object parameter)
{
if(CanExecute(parameter)&& _execute!= null)_execute(parameter)
}
}
然后您的 / code>类需要公开,例如 ICommand DeleteCmd 属性:
class Dog
{
...
private RelayCommand _deleteCmd;
private void DoDelete(object parameter)
{
// put delete action here
}
public ICommand DeleteCmd
{
get
{
if(_deleteCmd == null)_deleteCmd = new RelayCommand(o => DoDelete(o));
return _deleteCmd;
}
}
}
然后你绑定它这个:
< StackPanel Orientation ="Horizontal">
< TextBlock Text ="{Binding Name}"/>
< TextBlock Text ="{Binding Breed}"/>
< TextBlock Text ="{Binding Weight}"/>
< Button Command ="{Binding DeleteCmd}"/>
< / StackPanel>
在WPF中的ItemsControl中使用事件和命令(Using events and Commands within ItemsControl in WPF)的更多相关文章
- WPF使用MVVM(三)-事件转命令
WPF使用MVVM(三)-事件转命令 上一节介绍了WPF中的命令,可是仅仅介绍的是WPF框架给我们提供的点击命令,也就是用Command属性来绑定一个命令,用来响应按钮的点击行为!显然这是不够的,界面 ...
- WPF: 在 MVVM 设计中实现对 ListViewItem 双击事件的响应
ListView 控件最常用的事件是 SelectionChanged:如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实 ...
- 【转】【WPF】WPF中的Button的MouseDown事件不触发问题
按照WPF的帮助说明,某些控件的路由事件被内部处理了,已经被标记为Handled,自行定义的事件处理代码便不再起作用了,有时候会很郁闷! 不过WPF提供了必要的方法. 1)使用相应的Preview事件 ...
- WPF老矣,尚能饭否——且说说WPF今生未来(中):策略
本文接上文<WPF老矣,尚能饭否——且说说WPF今生未来(上):担心>继续. “上篇”中部分精彩的点评: 虽然WPF不再更新了,但是基于WPF的技术还是在发展着,就比如现在的WinRT,只 ...
- WPF中嵌入WinForm中的webbrowser控件
原文:WPF中嵌入WinForm中的webbrowser控件 使用VS2008创建WPF应用程序,需使用webbrowser.从工具箱中添加WPF组件中的webbrowser发现其中有很多属性事件不能 ...
- WPF编程,C#中对话框自动关闭的一种方法。
原文:WPF编程,C#中对话框自动关闭的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details/8 ...
- 继续聊WPF——如何获取ListView中选中的项
在WPF中获Listview中选中的项,与WinForm里面有着很大的区别,要亲身去研究一下在WPF中如果处理,其实也不难,来,下面我们一起来通过一个简单的示例来感悟一下吧. 第一步就是建立一个WPF ...
- WPF实用指南一:在WPF窗体的边框中添加搜索框和按钮
原文:WPF实用指南一:在WPF窗体的边框中添加搜索框和按钮 在边框中加入一些元素,在应用程序的界面设计中,已经开始流行起来.特别是在浏览器(Crome,IE,Firefox,Opera)中都有应用. ...
- javascript中通过匿名函数进行事件绑定
随机推荐
- 谷粒商城--分布式基础篇(P1~P27)
谷粒商城--分布式基础篇P1~P27 去年3月份谷粒商城分布式基础.进阶.高级刚出的时候就开始学了,但是中途因为一些事就中断了,结果一直到现在才有时间重新开始学,看到现在网上这么多人都学完了,确实感觉 ...
- 入门Kubernetes-Service
一.前言 前一篇文章通过 Deployment 实现了Pod中服务实现滚动更新/回滚等操作:在真实应用场景中,需要将一组Pod提供给外部访问.而且Pod生命周期是短暂的,在 Pod 的生命周期过程中, ...
- CF1444D Rectangular Polyline[题解]
Rectangular Polyline 题目大意 给定 \(h\) 条长度分别为 \(l_1,l_2,--,l_h\) 的水平线段以及 \(v\) 条长度分别为 \(p_1,p_2,--.p_v\) ...
- 「CF568C」 New Language
「CF568C」 New Language 一眼 \(\texttt{2-SAT}\) . 然后不会了. 又看了一会儿,然后发现只要我们确定每个位置大于字典序的两种最小的字母是啥,然后按位贪心,这个问 ...
- 基于Mininet的网络拓扑搭建代码
1 import logging 2 import os 3 import time 4 import thread 5 import multiprocessing 6 7 from mininet ...
- 实验 1 Linux 系统的安装和常用命令
实验 1 Linux 系统的安装和常用命令 (题目) 一.实验目的 (1)掌握 Linux 虚拟机的安装方法.Spark 和 Hadoop 等大数据软件在 Linux 操作系统 上运行可以发挥最佳性能 ...
- ES6 模块export import
在 ES6 前, 实现模块化使用的是 RequireJS 或者 seaJS(分别是基于 AMD 规范的模块化库, 和基于 CMD 规范的模块化库).ES6 引入了模块化,其设计思想是在编译时就能确定模 ...
- vue+canvas实现炫酷时钟效果的倒计时插件(已发布到npm的vue2插件,开箱即用)
前言: 此事例是在vue组件中,使用canvas实现倒计时动画的效果.其实,实现效果的逻辑跟vue没有关系,只要读懂canvas如何实现效果的这部分逻辑就可以了 canvas动画的原理:利用定时器,给 ...
- Unittest方法 -- 测试分离
一.下面是it.py 脚本,把浏览器前置和后置条件分离了"""套件公用测试类可进行分离"""import unittestfrom sele ...
- 记录一个SQL语句 case select 1
select Code, CodeName, CodeAlias, ComCode, OtherSign from ldcode where codetype = 'edorapptype' and ...