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. java基础---类和对象(2)

    一.继承(extends) 面向对象的三大特性之一,当多个类中存在相同属性和行为时,将这些内容抽取到一个公共类中,让多个类(子类)吸收公共类(父类.超类)中已有特征和行为,而在多个类型只需要编写自己独 ...

  2. C语言:位运算符

    异或        ^     两个二进制位相同结果为0:不相同结果为1              1^1=0    1^0=1   0^1=1  0^0=1 按位或    |      两个二进制位 ...

  3. sql 建立新表

    USE [exam]GO /****** Object: Table [dbo].[tx] Script Date: 12/13/2020 22:19:59 ******/SET ANSI_NULLS ...

  4. 团队开发day04

    通过myurl.openConnection()连接一直连接失败,问题解决: 在一般的Java Web程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务, 但是如果 ...

  5. xampp的Apache服务无法启动 Apache的443端口被占用解决方法

    今天在使用本地的XAMPP的时候,发现Apache服务不能正常启动,根据以往的经验,可能是80端口或者443端口被占用导致的,所以对端口占用情况进行排查. 1. 执行xampp/apache/bin中 ...

  6. 【洛谷1339 [USACO09OCT]】热浪Heat Wave 图论+最短路

    AC代码 #include<bits/stdc++.h> using namespace std; const int MAXN=62000+10,INF=999999; struct E ...

  7. shell脚本(12)-特殊变量介绍

    一.特殊变量介绍: 1.$* :代表所有参数,其间隔为IFS内参数的第一个字元 2.$@ :与*星号类同,不同之处在于不参照IFS 3.$# :代表参数数量 4.$: 代表上一个指令的返回值 5.$- ...

  8. javascript 特殊字符 注意转义

  9. Java面向对象12——static详解

    static  package oop.demon01.demon07; ​ // static : public class Student { ​     private static int a ...

  10. 我是如何在一晚上拿到阿里巴巴Android研发offer的?

    图文无关 开篇 我找工作时是2018年. 那一年,BAT大量缩招,就业形势严峻,互联网寒冬消息蔓延. 最终我经过激烈角逐拼下了几个大厂offer,回顾往事,觉得分享出来,也许对你能有所借鉴. 简历 这 ...