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. 题解 CF311B Cats Transport

    前置芝士:斜率优化  剥下这道题的外壳,让它变为一道裸的斜率优化. 很容易想到状态,但复杂度显然过不去,也没有单调性,只能自己创造. 令 $$c[i] = t - sum[i],sum[i] = \s ...

  2. python使用笔记006-函数+json操作

    一.函数 函数:提高代码的复用性 1.1 函数的定义 1 def hello(): 2 print('hello') 3 print('fdsfjslkfs') 4 5 #函数不调用就不会执行 6 h ...

  3. C语言:读写TXT

    fopen() 改为: if((fp=fopen("1s.txt","w+"))==NULL) fputc(p,fp); 改为:fprintf(fp," ...

  4. win10禁止粘滞键 禁止按5次shift开启粘滞键

    如果你感觉粘滞键的快捷键影响了你的使用或想强行更改连续按5次上档键的指向的话,建议用你需要的程序替换%windir%\system32文件夹下面的sethc.exe @echo offclsdel / ...

  5. 什么是 BPMN ?为什么我们要用 BPMN 和工作流 ?

    BPMN 和 Activiti 介绍 工作流介绍 在任何行业和企业中,都有各种各样的流程,例如: 请假流程 报销流程 入职流程 离职流程 出差流程 等等-- 就算你自己没有设计过工作流,那么你每天肯定 ...

  6. 【Azure Developer】【Python 】使用 azure.identity 和 azure.common.credentials 获取Azure AD的Access Token的两种方式

    问题描述 使用Python代码,展示如何从Azure AD 中获取目标资源的 Access Token. 如要了解如何从AAD中获取 client id,client secret,tenant id ...

  7. GetOverlappedResult 函数

    BOOL GetOverlappedResult( HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferre ...

  8. Webstorm 快速补全

    el-row>el-col*3>[:span='7'] 按Tab <el-row> <el-col> <div :span="">& ...

  9. Redis挂了,流量把数据库也打挂了,怎么办?

    你好呀,我是歪歪. 是这样的,前几天有个读者给我发消息,说面试的时候遇到一个场景题: 他说他当时,一时间竟然找不到回答问题的角度,感觉自己没有回答到点子上. 我仔细想了一下,确实是感到这个问题有一丝丝 ...

  10. 论文笔记:(CVPR2017)PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation

    目录 一. 存在的问题 二. 解决的方案 1.点云特征 2.解决方法 三. 网络结构 四. 理论证明 五.实验效果 1.应用 (1)分类: ModelNet40数据集 (2)部件分割:ShapeNet ...