WPF:自定义DataGrid,双向绑定,禁用行,行索引

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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值