在我们的项目中经常要用到数据模板,最近做的一个项目中在数据模板中要放一些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. BZOJ4327:[JSOI2012]玄武密码(SAM)

    Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此.  ...

  2. Apache 2.4.27 局域网访问提示 You don't have permission to access / on this server

    问题: 本机用localhost和ip都可以访问,局域网不可以访问,并且出现提示 You don't have permission to access / on this server. 解决: 如 ...

  3. mysql执行顺序

    SELECT语句执行顺序 SELECT语句中子句的执行顺序与SELECT语句中子句的输入顺序是不一样的,所以并不是从SELECT子句开始执行的,而是按照下面的顺序执行: 开始->FROM子句-& ...

  4. day25 Python

    一.day24复习 class school: x=1 #__init__初始化函数,用来帮类实例化一个具体的对象 def __init__(self,name,addr): #前面的Name是一个需 ...

  5. eclipse新建maven web项目

    使用eclipse版本如下,已集成了Maven,只需要配置下即可 一.下载eclipse,解压安装 二.下载maven,解压安装 三.修改${maven_home}/config/settings.x ...

  6. windows系统VS2017编译boost

    1. 下载boost, 解压,进入boost源目录 2. 打开vs2017 x86 CMD工具,输入bootstrap.bat,等待初始化完毕 x86编译 bjam stage --toolset=m ...

  7. ftp环境搭建并创建虚拟用户

    1. 首先安装ftp yum install -y vsftpd 2. 修改配置文件   cd /etc/vsftpd /etc/vsftpd/vsftpd.conf //主配置文件,核心配置文件 / ...

  8. Python排序算法——选择排序

    有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10787340.html 一.选择排序(Sele ...

  9. odoo11 审批流中行总额与申请单总额的计算问题

    一. 问题的描述 在做审批流的过程中,涉及到这样一个问题,用户申请的行总额需要根据当前行的数量和单价相乘计算得出,这本来是一个很简单的功能需求,利用odoo的计算方法就可以轻松实现,但是在在view页 ...

  10. Vue.js 系列教程 1:渲染,指令,事件

    原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...