在我们的项目中经常要用到数据模板,最近做的一个项目中在数据模板中要放一些RadioButton,其中每一个RadioButton设置了Checked事件,如果直接在View层写Checked事件的话不符合MVVM的设计思想,View层尽量只做和界面相关的绑定,而把所有的逻辑都写在ViewModel层中,但是如何才能把我们常见的.net事件绑定到Command上面呢?在该项目中我们使用了System.Windows.Interactivity下面的EventTriggers来进行相关的命令绑定,System.Windows.Interactivity.dll 中的 Interaction 可以帮助我们实现对命令的绑定,所以我们需要引用该文件到项目中,这个文件是微软的Blend中提供的。引用的方式包括两种:第一种是使用 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 来引用相关的命名空间,另外一种是通过xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"来引用该命名空间,记得在引用之前要添加对相关的DLL的引用,这个是第一步,后面就是对具体的内容的引用,这里贴出相关的核心的代码。

<ListBox x:Name="radioButtonListBox" ItemsSource="{Binding AllRadioButtonModels,Mode=TwoWay}">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="2" Columns="2" IsItemsHost="True">
</UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="#eee" BorderBrush="Blue" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<Button Content="qqq" Command="{Binding DataContext.RadioButtonCheckedCommand,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=Self}}"></Button>
<RadioButton GroupName="GroupOne" Content="{Binding BindingContent,Mode=TwoWay}" IsChecked="{Binding IsSelected,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding DataContext.MyCommandInstance,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

我们再看一下具体绑定的DataContext,在我们的MainWindow.cs 中 this.DataContext = RadioButtonViewModels.Instance;直接将一个RadioButtonViewModels的一个静态实例作为Window的DataContext,这里需要特别注意的地方是在模板中我们必须通过相关资源来找到这个DataContext,这里 Command="{Binding DataContext.MyCommandInstance,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"这个写法非常重要,MyCommandInstance是我们定义的一个命令,这个命令属于DataContext,另外还必须通过RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}来找到这个Window,如果我们定义的控件直接是在Grid中而不是在模板中的话,我们直接通过下面的方式就能够找到DataContext,这个特别需要注意,如果不是定义在模板中,那么程序会通过逻辑树一步步向上查找最终找到这个DataContext,但是在模板中不行,这个需要特别引起注意。

           <RadioButton Content="测试程序">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>

  另外一部分很重要的部分就是ViewModel层,在该层中我们通过三种不同的方式来进行命令绑定,这里首先介绍一下通过Microsoft.Practices.Prism.dll下面的DelegateCommand方法,首先定义public DelegateCommand<object> MyCommandRadioButtonCheckedInstance { get; private set; }属性,定义好属性之后,我们通过MyCommandRadioButtonCheckedInstance = new DelegateCommand<object>(MyCommandRadioButtonCheckedMethod,CanExecute);来为这个属性赋值,在我们的构造函数中,前面一个是一个委托执行的方法是带object类型的参数的,在定义好这些函数之后我们就可以将该命令绑定到View层中。第二种是通过 GalaSoft.MvvmLight.dll下面的RelayCommand类来进行命令的绑定,这个原理也差不多,具体方法请参考下面的文档。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.Prism.Commands;
using TestRadioButton.GetDataSource;
using TestRadioButton.Models; namespace TestRadioButton.ViewModels
{
public class RadioButtonViewModels
{
public RadioButtonViewModels()
{
allRadioButtonModels = DataSources.GetRadioButtonBindingSource();
MyCommandInstance = new MyCommand(MyCommandMethod);
MyCommandRadioButtonCheckedInstance = new DelegateCommand<object>(MyCommandRadioButtonCheckedMethod,CanExecute);
RadioButtonCheckedCommand = new RelayCommand<object>(RadioButtonCheckedCommandMethod);
} //自定义命令
public MyCommand MyCommandInstance { get; private set; } private void MyCommandMethod(object sender)
{
if (sender is string)
{
MessageBox.Show("Hello," + sender.ToString());
} } //自定义命令
public DelegateCommand<object> MyCommandRadioButtonCheckedInstance { get; private set; } public bool CanExecute(object parameter)
{
return true;
} private void MyCommandRadioButtonCheckedMethod(object sender)
{
if (sender is string)
{
MessageBox.Show(sender.ToString()+ " is Checked!");
} } public RelayCommand<object> RadioButtonCheckedCommand { get; private set; }
private void RadioButtonCheckedCommandMethod(object sender)
{
if (sender != null)
{
MessageBox.Show(sender.ToString()+" is Checked!");
} } public static RadioButtonViewModels instance = null;
public static RadioButtonViewModels Instance
{
get
{
if (instance != null)
{
return instance;
}
else
{
instance = new RadioButtonViewModels();
return instance;
}
}
set
{
if (value != instance)
{
instance = value;
}
} } private ObservableCollection<RadioButtonModels> allRadioButtonModels = new ObservableCollection<RadioButtonModels>();
public ObservableCollection<RadioButtonModels> AllRadioButtonModels
{
get
{
return allRadioButtonModels;
}
set
{
if (value != allRadioButtonModels)
{
allRadioButtonModels = value;
}
} } }
}

下面着重介绍第三种通过继承ICommand接口的方式来实现命令的绑定,这里首先贴出相关代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; namespace TestRadioButton
{
public class MyCommand:ICommand
{
public MyCommand(Action<object> action)
{
if (action == null)
{
throw new ArgumentNullException();
}
_action = action; } private readonly Action<object> _action; private bool _isEnabledExecute = true;//默认为启用状态 public bool IsEnabledExecute
{
get
{
return _isEnabledExecute;
}
set
{
if (value != _isEnabledExecute)
{
_isEnabledExecute = value;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this,new EventArgs());
} } } } #region ICommand 接口
public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter)
{
return _isEnabledExecute;
} public void Execute(object parameter)
{
_action(parameter);
}
#endregion }
}

这里我们来实现接口中的Execute和CanExecute方法,在ViewModel层中,首先定义 public MyCommand MyCommandInstance { get; private set; }属性,紧接着为这个属性来赋值,MyCommandInstance = new MyCommand(MyCommandMethod);然后再写一些委托函数以及回调方法,在我们的主窗体中我们实现了这一方法。

 <Button Content="我的未来不是梦!" Height="" Command="{Binding MyCommandInstance}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Self}}"></Button>
<ToggleButton Height="" Content="启动/禁用" IsChecked="{Binding MyCommandInstance.IsEnabledExecute}"></ToggleButton>

这里通过点击ToggleButton就能控制Button是否有效。这里不再赘述。通过上面的几种命令绑定的方式我们就能实现在如何在DataTemplate中绑定RadioButton的Checked事件,重点是开始讲到的如何在DataTemplate中找到Datacontext,这点需要引起注意。

下面贴出整个View层的代码:

<Window x:Class="TestRadioButton.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity"
Title="MainWindow" Height="" Width=""> <Window.Resources>
</Window.Resources>
<Grid>
<StackPanel>
<Button Content="我的未来不是梦!" Height="" Command="{Binding MyCommandInstance}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Self}}"></Button>
<ToggleButton Height="" Content="启动/禁用" IsChecked="{Binding MyCommandInstance.IsEnabledExecute}"></ToggleButton>
<Button Content="" Height="" Command="{Binding MyCommandRadioButtonCheckedInstance}" CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}">
</Button>
<Button x:Name="third" Content="" Height="" Command="{Binding MyCommandRadioButtonCheckedInstance}" CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}">
</Button>
<Button Content="" Height=""></Button>
<Button Content="qqq" Command="{Binding RadioButtonCheckedCommand}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Self}}"></Button>
<RadioButton Content="测试程序">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
<ListBox x:Name="radioButtonListBox" ItemsSource="{Binding AllRadioButtonModels,Mode=TwoWay}">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="" Columns="" IsItemsHost="True">
</UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="#eee" BorderBrush="Blue" BorderThickness="">
<StackPanel Orientation="Horizontal">
<Button Content="qqq" Command="{Binding DataContext.RadioButtonCheckedCommand,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=Self}}"></Button>
<RadioButton GroupName="GroupOne" Content="{Binding BindingContent,Mode=TwoWay}" IsChecked="{Binding IsSelected,Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding DataContext.MyCommandInstance,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" CommandParameter="{Binding Content,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</Window>

  

如何在DataTemplate中绑定RadioButton的Checked事件的更多相关文章

  1. wpf中如何在xaml中绑定cs中类的属性

    cs代码:/// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWin ...

  2. 如何在Vue2中实现组件props双向绑定

    Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...

  3. 如何在FineUIMvc(ASP.NET MVC)视图中绑定多个模型?

    起因 这是知识星球内的一个网友提出的,按理说ASP.NET MVC中一个视图只能绑定一个模型(Model),在视图顶部标识如下: @model IEnumerable<FineUICore.Ex ...

  4. 2018-8-10-win10-uwp-如何在DataTemplate绑定方法

    title author date CreateTime categories win10 uwp 如何在DataTemplate绑定方法 lindexi 2018-08-10 19:16:50 +0 ...

  5. [原创]如何在Parcelable中使用泛型

    [原创]如何在Parcelable中使用泛型 实体类在实现Parcelable接口时,除了要实现它的几个方法之外,还另外要定义一个静态常量CREATOR,如下例所示: public static cl ...

  6. 如何在XAMPP中设置多个网站

    xampp 是一个非常方便的本地 apache + php + mysql 的调试环境,在本地安装测试 WordPress 等各种博客.论坛程序非常方便.今天我们来给大家介绍一下,如何使用 XAMPP ...

  7. jqGrid中实现radiobutton的两种做法

    http://blog.sina.com.cn/s/blog_4f925fc30102e27j.html   jqGrid中实现radiobutton的两种做法 ------------------- ...

  8. WPF的ListBox中的RadioButton不能单选问题

    WPF不知道是微软故意弄的还是真的匆忙的推出的产品,在实际开发过程中有很多小问题解决很麻烦. 今天主要说一下ListBox中使用RadioButton的时候里面的RadioButton不能单选!居然成 ...

  9. WPF 在事件中绑定命令(不可以在模版中绑定命令)

    其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实现将命令绑定到事件中. 上一篇中我们介绍了MVVMLight中的命令的用法,那么仅仅知道命令是 ...

随机推荐

  1. Mybatis之插件拦截

    参考:http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默 ...

  2. Spring Kafka整合Spring Boot创建生产者客户端案例

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code 创建一个kafka-producer-master的maven工程.整个项目结构如下: ...

  3. 003_生成器(generator)内部解析

    #http://kb.cnblogs.com/page/87128/(未看完)

  4. hyperledger中文文档学习-2-简介

    参考https://hyperledgercn.github.io/hyperledgerDocs/blockchain_zh/ Hyperledger区块链框架(https://blog.csdn. ...

  5. String,StringBuffer,StringBuilder的区别与共同点

    1. String与StringBuffer,StringBuilder的区别: String为什么不可变:String存储数据是有final修饰的字符数组private final char val ...

  6. Linux并发与同步专题 (2)spinlock

    关键词:wfe.FIFO ticket-based.spin_lock/spin_trylock/spin_unlock.spin_lock_irq/spin_lock_bh/spin_lock_ir ...

  7. redis底层设计(三)——redis数据类型

    今天我们来看一下redis的数据类型.既然redis的键值对可以保存不同类型的值,那么很自然就需要对键值对的类型进行检查以及多态处理.下面我们将对redis所使用的对象系统进行了解,并分别观察字符串. ...

  8. 网络应用简记(4):DNS使用

    dns,domain name system,域名系统,把域名转化成ip的系统. 先来看几上工具的使用,这几个工具都能把域名转换成ip,都使用了dns.dns就好比数据库,通过对它的查询,能给url找 ...

  9. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 用户密码安全增强

    系统的用户密码是有多少重要大家应该心里都有数,一个系统的密码若是大批量泄露,哪怕是少数几个人密码泄露了,都是致命的. 1: 系统里不要保存明文密码,那是引诱人家犯罪.2: 首先防范的不是外鬼,先需要防 ...

  10. Solrcloud(Solr集群)

    Solrcloud(Solr集群) Solrcloud介绍: SolrCloud(solr集群)是Solr提供的分布式搜索方案. 当你需要大规模,容错,分布式索引和检索能力时使用SolrCloud. ...