当下拉框值发生改变后,若要通知改变内存的值改变,要用到
UpdateSourceTrigger
属性,则这样写:
<DataTemplate>
<ctrl:NumComboBoxCtrl Width="50"
mySelectedValue="{Binding stu.Score,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Cursor="Hand"
</DataTemplate>
完整代码如下:
<Window x:Class="CustomControl.knowledge.TestCellTemplateWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CustomControl.knowledge"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:ctrl="clr-namespace:CustomControl.UserControl"
mc:Ignorable="d"
Title="TestCellTemplateWindow" Height="450" Width="800" WindowStartupLocation="CenterOwner"
x:Name="me">
<Window.Resources>
<local:StudentYesNoToBooleanConverter x:Key="yesNoCvt"/>
<local:DebugDummyConverter x:Key="debugCvt"/>
<local:GenderColorConverter x:Key="genderCvt"/>
<Style x:Key="DataGridTextColumnCenterSytle" TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style x:Key="GenderDataGridTextColumnCenterSytle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DataGridTextColumnCenterSytle}">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="ToolTip" Value="{Binding stu.Gender}"/>
<Setter Property="Foreground" Value="{Binding stu.Gender,Converter={ StaticResource genderCvt}}"/>
</Style>
<Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource MaterialDesignGridViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</Window.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<DataGrid x:Name="datagrid" AutoGenerateColumns="False" CanUserSortColumns="True" CanUserAddRows="False" IsReadOnly="True"
LoadingRow="gd_LoadingRow" Style="{StaticResource MaterialDesignDataGrid}"
HorizontalContentAlignment="Left" VerticalContentAlignment="Center" MouseDoubleClick="datagrid_MouseDoubleClick"
<DataGrid.Columns>
<!--存储每一行的guid-->
<DataGridTextColumn Binding="{Binding ID}" Visibility="Collapsed"/>
<!--序号-->
<DataGridTemplateColumn x:Name="Num">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=DataGridRow },Path=Header}" FontSize="16"
TextAlignment="Center" Foreground="Black" VerticalAlignment="Center" Style="{StaticResource MaterialDesignHeadline1TextBlock}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--复选按钮-->
<DataGridCheckBoxColumn IsReadOnly="False" Binding="{Binding IsValid,UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.HeaderTemplate >
<DataTemplate>
<CheckBox Click="CheckBox_Click" HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource MaterialDesignCheckBox}"
></CheckBox>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
<DataGridCheckBoxColumn.CellStyle >
<Style BasedOn="{StaticResource MaterialDesignDataGridCell }" TargetType="DataGridCell">
<Setter Property="CheckBox.VerticalAlignment" Value="Center"></Setter>
<Setter Property="CheckBox.HorizontalAlignment" Value="Center"></Setter>
<Setter Property="CheckBox.Cursor" Value="Hand"/>
</Style>
</DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>
<DataGridTextColumn Binding="{Binding stu.UserName}" Width="100" Header="学生名称" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}" ElementStyle="{StaticResource DataGridTextColumnCenterSytle}"/>
<DataGridTextColumn Binding="{Binding stu.Gender}" Width="100" Header="性别" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}" ElementStyle="{StaticResource GenderDataGridTextColumnCenterSytle}" />
<DataGridTextColumn Binding="{Binding stu.ClassName}" Width="100" Header="班级名称" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}" ElementStyle="{StaticResource DataGridTextColumnCenterSytle}"/>
<DataGridTextColumn Binding="{Binding stu.Address}" Width="120" Header="地址" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}" ElementStyle="{StaticResource DataGridTextColumnCenterSytle}" />
<!--成绩-->
<DataGridTemplateColumn Header="成绩" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ctrl:NumComboBoxCtrl Width="50"
mySelectedValue="{Binding stu.Score,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Cursor="Hand"
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="Auto" Header="操作" HeaderStyle="{StaticResource MaterialDesignDataGridColumnHeader}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<Button Content="编辑" Style="{StaticResource MaterialDesignOutlinedButton}"/>
<Button Margin="8 0 0 0" Content="删除" Style="{StaticResource MaterialDesignOutlinedButton}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource MaterialDesignDataGridRow}">
<Setter Property="IsEnabled" Value="{Binding stu.YesNo,Converter={StaticResource yesNoCvt}}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
</Grid>
<ListView Grid.Row="1" x:Name="listView" ItemContainerStyle="{StaticResource ListViewItemStyle}"
<ListView.View>
<GridView>
<GridViewColumn
Header="IsChecked" HeaderContainerStyle="{StaticResource MaterialDesignOutlinedButton}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsValid}"
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
DisplayMemberBinding="{Binding stu.UserName}"
Header="UserName" HeaderContainerStyle="{StaticResource MaterialDesignOutlinedButton}"/>
<GridViewColumn
DisplayMemberBinding="{Binding stu.Gender}"
Header="Gender" HeaderContainerStyle="{StaticResource MaterialDesignOutlinedButton}"/>
<GridViewColumn
DisplayMemberBinding="{Binding stu.ClassName}"
Header="ClassName" HeaderContainerStyle="{StaticResource MaterialDesignOutlinedButton}"/>
<GridViewColumn
DisplayMemberBinding="{Binding stu.Score}"
Header="Score" HeaderContainerStyle="{StaticResource MaterialDesignOutlinedButton}"/>
</GridView>
</ListView.View>
</ListView>
<Button Content="提交" Margin="5" Grid.Row="2" Click="Submit_Click"/>
</Grid>
</Window>
using CustomControl.Base;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace CustomControl.knowledge
/// <summary>
/// TestCellTemplateWindow.xaml 的交互逻辑
/// </summary>
public partial class TestCellTemplateWindow : Window
public TestCellTemplateWindow()
InitializeComponent();
students.Add(
new BasicInfo() { stu = new Student() { UserName = "小王", ClassName = "高二三班", Address = "广州市", Gender = "男",YesNo=1 },ID="111235991" }
students.Add(
new BasicInfo() { stu = new Student() { UserName = "小李", ClassName = "高三六班", Address = "清远市", Gender = "女", YesNo = 2 }, ID = "112236992" }
students.Add(
new BasicInfo() { stu = new Student() { UserName = "小张", ClassName = "高一一班", Address = "深圳市", Gender = "女", YesNo = 1 }, ID = "113237994" }
students.Add(
new BasicInfo() { stu = new Student() { UserName = "小黑", ClassName = "高一三班", Address = "赣州市", Gender = "男", YesNo = 2 }, ID = "114238996" }
datagrid.ItemsSource = students;
listView.ItemsSource = students;
private ObservableCollection<BasicInfo> students = new ObservableCollection<BasicInfo>();
/// <summary>
/// 全选
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CheckBox_Click(object sender, RoutedEventArgs e)
CheckBox headercb = (CheckBox)sender;
for (int i = 0; i < datagrid.Items.Count; i++)
//获取行
DataGridRow neddrow = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromIndex(i);
//获取该行的某列
CheckBox cb = (CheckBox)datagrid.Columns[2].GetCellContent(neddrow);
IDataGridListRow info =(IDataGridListRow) datagrid.Columns[2].GetCellContent(neddrow).DataContext;
bool isEnable = neddrow.IsEnabled;
if (isEnable)
cb.IsChecked = headercb.IsChecked;
info.IsValid= (bool)headercb.IsChecked;
/// <summary>
/// 加载每一行的索引
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gd_LoadingRow(object sender, DataGridRowEventArgs e)
e.Row.Header = e.Row.GetIndex() + 1;
/// <summary>
/// 提交
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Submit_Click(object sender, RoutedEventArgs e)
for (int i = 0; i < datagrid.Items.Count; i++)
//获取行
DataGridRow neddrow = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromIndex(i);
bool isEnable = neddrow.IsEnabled;
IDataGridListRow info = (IDataGridListRow)datagrid.Columns[1].GetCellContent(neddrow).DataContext;
string isVaild = info.IsValid.ToString();
string id = info.ID.ToString();
MessageBox.Show("iSValid: " + isVaild + "\nid : " + id+"\n isEnable: " +
""+isEnable.ToString());
/// <summary>
/// 行双击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void datagrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
DataGrid datagrid = sender as DataGrid;
IDataGridListRow cellValue =(IDataGridListRow) datagrid.SelectedValue;
if (cellValue == null) return;
MessageBox.Show("ID: " + cellValue.ID.ToString());
#region Converter
/// <summary>
/// 列表性别字段的颜色:
/// 男:blue,女:pink,其他:不变化
/// 注:单向转换
/// </summary>
public class GenderColorConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
if (value != null)
if (!string.IsNullOrWhiteSpace(value.ToString()))
string gender = value.ToString().Trim();
if ("男".Equals(gender))
return new System.Windows.Media.SolidColorBrush(Colors.Blue);
else if ("女".Equals(gender))
return new SolidColorBrush(Colors.DeepPink);
return new SolidColorBrush(Colors.Black);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
return value;
/// <summary>
/// 是否禁用转换器
/// 默认启用
/// 注:单向转换
/// </summary>
public class StudentYesNoToBooleanConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
if (value != null)
if (string.IsNullOrWhiteSpace(value.ToString()))
return true;
YesNo yn = (YesNo)Enum.Parse(typeof(YesNo), value.ToString());
return yn != YesNo.是;
return true;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
return value;
/// <summary>
/// 用于调试
/// </summary>
public class DebugDummyConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
Debugger.Break();
return value;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
Debugger.Break();
return value;
/// <summary>
/// 某行是否可以编辑 --枚举
/// </summary>
public enum YesNo
是 = 1,
否 = 2
#endregion
#region Model
public class BasicInfo:DataGridListRowBase
public Student stu { get; set; }
public class Student: ViewModelBase
#region private fields
private float score = 10;
#endregion
#region public property
public string UserName { get; set; }
public string ClassName { get; set; }
public string Address { get; set; }
public string Gender { get; set; } = "未说明";
public int YesNo { get; set; }
public float Score
get => score;
set => SetProperty(ref score, value);
#endregion
public class DataGridListRowBase : ViewModelBase, IDataGridListRow
#region private fields
private string id;
private bool isValid=true;
#endregion
#region public property
/// <summary>
/// 列表主键ID
/// </summary>
public string ID { get=>id; set=> SetProperty(ref id, value); }
/// <summary>
/// 是否选择
/// </summary>
public bool IsValid { get => isValid;set=> SetProperty(ref isValid, value);}
#endregion
public interface IDataGridListRow
/// <summary>
/// 列表主键ID
/// </summary>
string ID { get; set; }
/// <summary>
/// 是否选择
/// </summary>
bool IsValid { get; set; }
#endregion
<UserControl x:Class="CustomControl.UserControl.NumComboBoxCtrl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CustomControl.UserControl"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" x:Name="me">
<UserControl.Resources>
<Style x:Key="myComboBox" TargetType="ComboBox" BasedOn="{StaticResource MaterialDesignComboBox}">
</Style>
</UserControl.Resources>
<ComboBox x:Name="comboBox"
SelectedValue="{Binding ElementName=me ,Path=mySelectedValue}"
Style="{StaticResource myComboBox}" />
</Grid>
</UserControl>
using System.Collections.Generic;
using System.Windows;
namespace CustomControl.UserControl
/// <summary>
/// NumComboBoxCtrl.xaml 的交互逻辑
/// </summary>
public partial class NumComboBoxCtrl : System.Windows.Controls.UserControl
public NumComboBoxCtrl()
InitializeComponent();
double item = 0;
for (int i = 0; i <= 200; i++)
list.Add(item.ToString());
item = item + 0.5;
this.comboBox.ItemsSource = list;
private List<string> list = new List<string>();
public string mySelectedValue
get { return (string)GetValue(mySelectedValueProperty); }
set { SetValue(mySelectedValueProperty, value); }
// Using a DependencyProperty as the backing store for mySelectedValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty mySelectedValueProperty =
DependencyProperty.Register("mySelectedValue", typeof(string), typeof(NumComboBoxCtrl), new PropertyMetadata("0"));
public abstract class ViewModelBase : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
if (!EqualityComparer<T>.Default.Equals(field, newValue))
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
return false;
以下代码实现了DataGrid的简单绑定List数据源
重点要提一下的是,绑定List数据源,但是不能直接用List。比如下面的代码,使用List<GridItem>只能实现数据修改的绑定,但是数据添加,删除都无法实现双向绑定。所以这里要改用ObservableCollection<GridItem>,其他代码都不用改。只要类型改下即可,WPF内部已经实现了添加,删除等的...
private void dataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
e.Cancel = true;
原理就是单元格编辑事件:CellBeginEdit(编辑之前发生),当要编辑时取消该事件,达到禁止编辑的目的
二、行禁止编辑
private void dataGridView_BeginEdit(object sender,
public ObservableCollection<object> ObservableObj; public MainWindow() { InitializeComponent(); ObservableObj = new ObservableCollecti...
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
//我DataGrid绑定的是List<PracticeInfo>
//每个Item则是一个PracticeInfo对象
//根据自己绑定的对象进行修改
PracticeInfo p...
<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" FontSize="14" RowHeaderWidth="40"
SelectionMode="Single" CanUserAddRows="False" ItemsSource="{Binding}" LoadingR...
{BindingBB,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}
转载于:https://www.cnblogs.com/Mindy-hym/p/11431069.html...
<DataGridTemplateColumn Header="厚度数据" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
1)在FrameworkElement类下有两个重要的属性。利用这两个属性,可以实现UI数据直接与后台的类进行绑定2)前端UI界面属性值等动态与后台绑定的方式有多种,此处列出后台设置DataContext以及前端设置DataContext的两种方式,以及数据双向绑定的最佳实践纯前端的方式好处在于,编译一下,就可以在设计阶段看到效果。
1)先定义好我们的类
2)在前端按照步骤引入
后台设置DataContext
在设计阶段是看不到效果的,但是灵活性更高,属性值不用写死
1)定义一个类
2)在当前窗口加载时,进
Detailed change notification: Unlike otherDependencyObjectobjects, aFreezableobject provides change notifications when sub-property values change.
大意就是和其他的DependencyObject相比,在子属性值更改时,Freezable对象提供更改通知。个人认为应...