如何在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中的命令的用法,那么仅仅知道命令是 ...
随机推荐
- python笔记31-使用ddt报告出现dict() -> new empty dictionary dict(mapping) 问题解决
使用ddt框架生成html报告的时候,出现:dict() -> new empty dictionary dict(mapping) -> new dictionary initializ ...
- selenium之frame
https://blog.csdn.net/huilan_same/article/details/52200586
- Python:Day18 os模块、logging模块、正则表达式
迭代器 满足迭代器协议: 1.内部有next方法 2.内部有iter()方法 os模块 import os print(os.getcwd()) #C:\Users\Lowry\PycharmProj ...
- 缓存表 内存表(将表keep到内存)
缓存表 内存表(将表keep到内存) 一.引言: 有时候一些基础表需要非常的频繁访问,尤其是在一些循环中,对该表中的访问速度将变的非常重要.为了提高系统的处理性能,可以考虑将一些表及索引读取并 ...
- Spring Security(三):1、Getting Started
The later parts of this guide provide an in-depth discussion of the framework architecture and imple ...
- 小技巧:改变 VS Code 工作区页面背景
效果图: 步骤(一): 1.点击页面左上角 文件/首选项/设置 2.在搜索框中输入:background 如下图. 3.找到 Background: Custom Images 选项并点击在 ...
- Ubuntu14.04下如何安装TensorFlow
一.安装Anaconda Anaconda官网(www.continuum.io/downloads) 也可以在(https://repo.continuum.io/archive/)上根据自己的操作 ...
- 从MFQ方法到需求分析
前几天看了一篇性能测试相关的文章:性能测试模型初探及应用方法分析,其中提到了MFQ分析方法.专门去查阅了MFQ相关的一些资料,学习了一番. 之后想起了以前看<Google的软件测试之道>这 ...
- Generative Adversarial Nets[Introduction]
0. 背景 通过阅读书籍<Pro Deep Learning with TensorFlow: A Mathematical Approach to Advanced Artificial In ...
- machine learning[GMM-EM]
介绍下EM算法和GMM模型,先简单介绍GMM的物理意义,然后给出最直接的迭代过程:然后再介绍EM. 1 高斯混合模型 高斯分布,是统计学中的模型,其输出值表示当前输入数据样本(一维标量,多维向量)的概 ...