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 ="Horizo​​ntal">
< 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 ="Horizo​​ntal">
< 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 ="Horizo​​ntal"> 
< 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)的更多相关文章

  1. WPF使用MVVM(三)-事件转命令

    WPF使用MVVM(三)-事件转命令 上一节介绍了WPF中的命令,可是仅仅介绍的是WPF框架给我们提供的点击命令,也就是用Command属性来绑定一个命令,用来响应按钮的点击行为!显然这是不够的,界面 ...

  2. WPF: 在 MVVM 设计中实现对 ListViewItem 双击事件的响应

    ListView 控件最常用的事件是 SelectionChanged:如果采用 MVVM 模式来设计 WPF 应用,通常,我们可以使用行为(如 InvokeCommandAction)并结合命令来实 ...

  3. 【转】【WPF】WPF中的Button的MouseDown事件不触发问题

    按照WPF的帮助说明,某些控件的路由事件被内部处理了,已经被标记为Handled,自行定义的事件处理代码便不再起作用了,有时候会很郁闷! 不过WPF提供了必要的方法. 1)使用相应的Preview事件 ...

  4. WPF老矣,尚能饭否——且说说WPF今生未来(中):策略

    本文接上文<WPF老矣,尚能饭否——且说说WPF今生未来(上):担心>继续. “上篇”中部分精彩的点评: 虽然WPF不再更新了,但是基于WPF的技术还是在发展着,就比如现在的WinRT,只 ...

  5. WPF中嵌入WinForm中的webbrowser控件

    原文:WPF中嵌入WinForm中的webbrowser控件 使用VS2008创建WPF应用程序,需使用webbrowser.从工具箱中添加WPF组件中的webbrowser发现其中有很多属性事件不能 ...

  6. WPF编程,C#中对话框自动关闭的一种方法。

    原文:WPF编程,C#中对话框自动关闭的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details/8 ...

  7. 继续聊WPF——如何获取ListView中选中的项

    在WPF中获Listview中选中的项,与WinForm里面有着很大的区别,要亲身去研究一下在WPF中如果处理,其实也不难,来,下面我们一起来通过一个简单的示例来感悟一下吧. 第一步就是建立一个WPF ...

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

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

  9. javascript中通过匿名函数进行事件绑定

随机推荐

  1. 「NOIP2017」宝藏

    「NOIP2017」宝藏 题解 博客阅读效果更佳 又到了一年一度NOIPCSP-S 赛前复习做真题的时间 于是就遇上了这道题 首先观察数据范围 \(1 \le n \le 12\) ,那么极大可能性是 ...

  2. java集合(1)-概述

    Java集合类是一种特别有用的工具类,可用于存储数量不等的对象,并可以实现常用的数据结构,如栈,队列等,此外Java集合还可以用于保存具有映射关系的关联数组.java集合大致可分为Set,List,Q ...

  3. 【LeetCode】560. 和为K的子数组

    560. 和为K的子数组 知识点:数组:前缀和: 题目描述 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 输入:nums = [1,1,1], k = 2 ...

  4. MyEclipse无法打开jsp文件(打开是空白的),但是可以打开java文件

    转载: 解决MyEclipse使用时打开JSP发生"An error has occurred,See error log for more details"错误的解决方法这个问题 ...

  5. .net core工具组件系列之Redis—— 第一篇:Windows环境配置Redis(5.x以上版本)以及部署为Windows服务

    Cygwin工具编译Redis Redis6.x版本是未编译版本(官方很调皮,所以没办法,咱只好帮他们编译一下了),所以咱们先下载一个Cygwin,用它来对Redis进行编译. Cygwin下载地址: ...

  6. MySQL触发器笔记

    当操作了某张数据表时,希望同时触发一些动作或行为,就可以使用触发器完成. 当操作微博表时,同时生成一条日志记录 -- 插入时触发 create trigger tri_weiboAdd after i ...

  7. 在 Golang 中实现一个简单的Http中间件

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的 ...

  8. 【LOJ 109 并查集】 并查集

    题目描述 这是一道模板题. 维护一个 n 点的无向图,支持: 加入一条连接 u 和 v 的无向边 查询 u 和 v 的连通性 由于本题数据较大,因此输出的时候采用特殊的输出方式:用 0 或 1 代表每 ...

  9. <textarea></textarea>标签的placeholder属性不生效问题

    <textarea></textarea>标签的placeholder属性不生效问题   1.在用到<textarea></textarea>标签时,设 ...

  10. CTF之隐写总结

    目测要更很久,因为今年有一件非常重要的事要完成,希望一切顺利  All The Best.