如何在DataTemplate中绑定RadioButton的Checked事件
在我们的项目中经常要用到数据模板,最近做的一个项目中在数据模板中要放一些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事件的更多相关文章
- wpf中如何在xaml中绑定cs中类的属性
cs代码:/// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWin ...
- 如何在Vue2中实现组件props双向绑定
Vue学习笔记-3 前言 Vue 2.x相比较Vue 1.x而言,升级变化除了实现了Virtual-Dom以外,给使用者最大不适就是移除的组件的props的双向绑定功能. 以往在Vue1.x中利用pr ...
- 如何在FineUIMvc(ASP.NET MVC)视图中绑定多个模型?
起因 这是知识星球内的一个网友提出的,按理说ASP.NET MVC中一个视图只能绑定一个模型(Model),在视图顶部标识如下: @model IEnumerable<FineUICore.Ex ...
- 2018-8-10-win10-uwp-如何在DataTemplate绑定方法
title author date CreateTime categories win10 uwp 如何在DataTemplate绑定方法 lindexi 2018-08-10 19:16:50 +0 ...
- [原创]如何在Parcelable中使用泛型
[原创]如何在Parcelable中使用泛型 实体类在实现Parcelable接口时,除了要实现它的几个方法之外,还另外要定义一个静态常量CREATOR,如下例所示: public static cl ...
- 如何在XAMPP中设置多个网站
xampp 是一个非常方便的本地 apache + php + mysql 的调试环境,在本地安装测试 WordPress 等各种博客.论坛程序非常方便.今天我们来给大家介绍一下,如何使用 XAMPP ...
- jqGrid中实现radiobutton的两种做法
http://blog.sina.com.cn/s/blog_4f925fc30102e27j.html jqGrid中实现radiobutton的两种做法 ------------------- ...
- WPF的ListBox中的RadioButton不能单选问题
WPF不知道是微软故意弄的还是真的匆忙的推出的产品,在实际开发过程中有很多小问题解决很麻烦. 今天主要说一下ListBox中使用RadioButton的时候里面的RadioButton不能单选!居然成 ...
- WPF 在事件中绑定命令(不可以在模版中绑定命令)
其实这也不属于MVVMLight系列中的东东了,没兴趣的朋友可以跳过这篇文章,本文主要介绍如何在WPF中实现将命令绑定到事件中. 上一篇中我们介绍了MVVMLight中的命令的用法,那么仅仅知道命令是 ...
随机推荐
- 详解Transformer模型(Atention is all you need)
1 概述 在介绍Transformer模型之前,先来回顾Encoder-Decoder中的Attention.其实质上就是Encoder中隐层输出的加权和,公式如下: 将Attention机制从Enc ...
- No.0
算法类 1.快速排序算法 2.树的非递归后序排序算法 3.希尔排序 4.冒泡排序 5.链表和链表转向 6.其他 设计模式 1.单例模式 2.工厂模式 3.抽象工厂模式 4.面向对象设计,ooa,o ...
- WiFi-ESP8266入门http(2-2)文件系统-复杂结构的网页 + 文本框交互WIFI信息
网友教程:https://blog.csdn.net/solar_Lan/article/details/74231360 通过网友教程,我们搭建了文件系统.在此基础上,我们增加WIFI交互. 现有功 ...
- 比起Windows,怎样解读Linux的文件系统与目录结构?
比起Windows,怎样解读Linux的文件系统与目录结构? Linux 和Windows的文件系统有些不同,在学习使用 Linux 之前,若能够了解这些不同,会有助于后续学习. 本文先对Window ...
- C#邮件发送类 简单实用 可自定义发件人名称
上图看效果 MailHelper: public class MailHelper { public bool SendMail(MailSender sender,out string errorM ...
- 一次linux服务器黑客入侵后处理
场景: 周一上班centos服务器ssh不可用,web和数据库等应用不响应.好在vnc可以登录 使用last命令查询,2号之前的登录信息已被清空,并且sshd文件在周六晚上被修改,周日晚上2点服务器 ...
- Paypal2017实习生-软件开发-B卷
1. [编程|15分] Calculate survival fishes时间限制:1秒空间限制:32768K题目描述Given two zero-indexed arrays A and B con ...
- PS调出冷绿色电影画面风格
原图 一.按照惯例先磨皮,我修照片的习惯是,先拉一层色阶,使直方图平均分配,画面会显得没那么灰,当然,这只是个人喜好,先加后加都没所谓. 二.由于脸部的亮度不够,显得有点脏.所以这一步主要是通过拉曲线 ...
- 多线程系列之四:Guarded Suspension 模式
一,什么是Guarded Suspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待.这种模式通过让线程等待来保证实例的安全性 二,实现一个简单的线程间通信的例子 一个线程(Clie ...
- alibaba druid
FAQ · alibaba/druid Wikihttps://github.com/alibaba/druid/wiki/FAQ sql 连接数不释放 ,Druid异常:wait millis 40 ...