当下拉框值发生改变后,若要通知改变内存的值改变,要用到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>
<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>
<Grid>
<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;
}
}