【愚公系列】2023年10月 WPF控件专题 DataGrid控件详解

举报
愚公搬代码 发表于 2023/09/30 23:49:01 2023/09/30
【摘要】 WPF控件是Windows Presentation Foundation(WPF)中的基本用户界面元素。它们是可视化对象,可以用来创建各种用户界面。WPF控件可以分为两类:原生控件和自定义控件。

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

WPF控件是Windows Presentation Foundation(WPF)中的基本用户界面元素。它们是可视化对象,可以用来创建各种用户界面。WPF控件可以分为两类:原生控件和自定义控件。

原生控件是由Microsoft提供的内置控件,如Button、TextBox、Label、ComboBox等。这些控件都是WPF中常见的标准用户界面元素。

自定义控件则允许开发人员使用XAML和C#等编程语言来创建个性化的用户界面元素。自定义控件可以根据需求提供更多的功能和自定义化选项,以及更好的用户体验。

🚀一、DataGrid控件详解

WPF中的DataGrid是一个非常强大和灵活的控件,它可用于展示和编辑数据。DataGrid可以与各种数据源进行绑定,如数据表、XML文件、对象集合等,并且可以进行列的自定义、排序、过滤和分组等操作。以下是一些常用的DataGrid控件属性和方法:

属性:

  • AutoGenerateColumns:指定是否自动生成列。
  • ItemsSource:指定数据源。
  • IsReadOnly:指定是否只读。
  • Columns:指定列集合。
  • RowHeaderWidth:指定行头宽度。
  • RowHeadersVisibility:指定行头的可见性。
  • SelectionMode:指定选择模式。

方法:

  • BeginEdit():开始编辑当前单元格。
  • CancelEdit():取消当前单元格的编辑状态。
  • CommitEdit():提交当前单元格的编辑状态。
  • CancelEdit():取消当前单元格的编辑状态。
  • Sort():对数据进行排序。
  • Refresh():刷新数据。

DataGrid还有许多其他的属性和方法,可以根据需求进行使用。

🔎1.属性介绍

WPF中DataGrid控件的常见属性如下:

  1. AutoGenerateColumns:是否自动生成列,默认为true。

  2. CanUserAddRows:是否允许用户新增行,默认为true。

  3. CanUserDeleteRows:是否允许用户删除行,默认为true。

  4. CanUserResizeColumns:是否允许用户调整列宽,默认为true。

  5. CanUserResizeRows:是否允许用户调整行高,默认为true。

  6. CanUserSortColumns:是否允许用户排序列,默认为true。

  7. IsReadOnly:是否只读,默认为false。

  8. HeadersVisibility:列头的可见性,默认为Column。

  9. SelectionMode:选择模式,有Single和Extended两种模式可选,默认为Extended。

  10. RowHeaderWidth:行头宽度。

  11. RowHeight:行高。

  12. AlternatingRowBackground:交替行的背景色。

  13. GridLinesVisibility:网格线的可见性,默认为None。

  14. ItemsSource:数据源。

  15. Columns:列集合,可以手动定义和配置每一列的属性。

🔎2.常用场景

WPF中DataGrid控件常用场景包括以下几个方面:

  1. 数据展示:DataGrid控件可以方便地展示数据表格,特别是当数据量比较大时,使用DataGrid可以快速地进行数据查看和筛选。

  2. 数据编辑:DataGrid控件可以支持数据的编辑,包括单元格编辑、行编辑和列编辑等方式,方便用户对数据进行修改和更新。

  3. 数据排序和筛选:DataGrid控件支持数据的排序和筛选功能,可以根据用户需求方便地对数据进行排序和筛选。

  4. 数据分页:DataGrid控件可以支持数据的分页显示,当数据量比较大时,可以将数据分页展示,方便用户进行快速的数据浏览和查找。

  5. 数据导入导出:DataGrid控件可以支持数据的导入和导出,可以将数据快速地导入到DataGrid中进行展示,也可以将DataGrid中的数据导出到其他文件格式中,方便数据的共享和使用。

  6. 自定义样式和模板:DataGrid控件可以根据用户需要进行自定义样式和模板,可自由修改表格的外观和布局,使数据的展示更加美观和易于阅读。

🔎3.具体案例

🦋3.1 数据绑定案例

<Window x:Class="WpfAppTest.DataGridWindow"
        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:WpfAppTest"
        mc:Ignorable="d"
        Title="DataGridWindow" Height="450" Width="600" Loaded="Window_Loaded">
        <Grid>
              
                <DataGrid HeadersVisibility="All" AutoGenerateColumns="False"  CanUserAddRows="False" IsReadOnly="False" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden"  AlternationCount="3" RowHeaderWidth="20"  GridLinesVisibility="All" SelectionUnit="FullRow" SelectionMode="Extended"  Background="White" Name="dgList"  ItemsSource="{Binding UserList}" >
                        <DataGrid.RowStyle>
                                <Style TargetType="DataGridRow">
                                        <Setter Property="Background" Value="Transparent"/>
                                        <Style.Triggers>
                                                <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                                                        <Setter Property="Background" Value="LightGray"/>
                                                </Trigger>
                                                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                                                        <Setter Property="Background" Value="LightBlue"/>
                                                </Trigger>
                                                <Trigger Property="ItemsControl.AlternationIndex" Value="2">
                                                        <Setter Property="Background" Value="Orange"/>
                                                </Trigger>
                                        </Style.Triggers>
                                </Style>
                        </DataGrid.RowStyle>
                        <DataGrid.Columns>
                                <DataGridTextColumn Header="编号" Binding="{Binding UserId}" Width="50"/>
                                <DataGridTextColumn Header="姓名" Binding="{Binding UserName}" Width="80">
                                        <DataGridTextColumn.HeaderTemplate>
                                                <DataTemplate>
                                                        <TextBlock Text="{Binding}" Foreground="Red"/>
                                                </DataTemplate>
                                        </DataGridTextColumn.HeaderTemplate>
                                     
                                </DataGridTextColumn>
                                <DataGridCheckBoxColumn Header="状态" Binding="{Binding UserState}" Width="50"/>
                                <DataGridComboBoxColumn Header="部门"  SelectedValueBinding="{Binding DeptId}"  Width="100" DisplayMemberPath="DeptName" SelectedValuePath="DeptId"  >
                                        <DataGridComboBoxColumn.ElementStyle>
                                                <Style TargetType="ComboBox">
                                                        <Setter Property="ItemsSource" Value="{Binding DataContext.DeptList,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"/>
                                                </Style>
                                        </DataGridComboBoxColumn.ElementStyle>
                                        <DataGridComboBoxColumn.EditingElementStyle>
                                                <Style TargetType="ComboBox">
                                                        <Setter Property="ItemsSource" Value="{Binding DataContext.DeptList,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"/>
                                                </Style>
                                        </DataGridComboBoxColumn.EditingElementStyle>
                                </DataGridComboBoxColumn>


                                <DataGridTemplateColumn Header="年龄"  Width="50" >
                                        <DataGridTemplateColumn.CellTemplate>
                                                <DataTemplate>
                                                        <Label Content="{Binding UserAge}" Foreground="Green" Background="LightBlue"/>
                                                </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                        <DataGridTemplateColumn.CellEditingTemplate>
                                                <DataTemplate>
                                                        <TextBox Text="{Binding UserAge}"/>
                                                </DataTemplate>
                                        </DataGridTemplateColumn.CellEditingTemplate>
                                </DataGridTemplateColumn>
                        </DataGrid.Columns>
                </DataGrid>

        </Grid>
</Window>

/// <summary>
/// 获取用户信息列表
/// </summary>
/// <returns></returns>
private List<UserInfoNew> GetUserList()
{
        List<UserInfoNew> list = new List<UserInfoNew>();
        string sql = "select UserId,UserName,UserState,UserAge,DeptId from UserInfos where DeptId>0";
        SqlDataReader dr = SqlHelper.ExecuteReader(sql, 1);
        while (dr.Read())
        {
                UserInfoNew user = new UserInfoNew();
                user.UserId = (int)dr["UserId"];
                user.UserName = dr["UserName"].ToString();
                user.UserState = (int)dr["UserState"] == 1 ? true : false;
                user.UserAge = (int)dr["UserAge"];
                user.DeptId = (int)dr["DeptId"];
                list.Add(user);
        }
        dr.Close();
        return list;
}

/// <summary>
/// 获取部门列表
/// </summary>
/// <returns></returns>
private List<DeptInfo> GetDepts()
{
        List<DeptInfo> list = new List<DeptInfo>();
        string sql = "select DeptId,DeptName from DeptInfos";
        SqlDataReader dr = SqlHelper.ExecuteReader(sql, 1);
        while (dr.Read())
        {
                DeptInfo dept = new DeptInfo();
                dept.DeptId = (int)dr["DeptId"];
                dept.DeptName = dr["DeptName"].ToString();
                list.Add(dept);
        }
        dr.Close();
        return list;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
        //首先,设置comboBox列的数据源   
        //colDept.DisplayMemberPath = "DeptName";
        //colDept.SelectedValuePath = "DeptId";
        //colDept.ItemsSource = GetDepts();
        //如果没有设置列的Name属性
        //DataGridComboBoxColumn deptCol = dgList.Columns[3] as DataGridComboBoxColumn;
        //deptCol.ItemsSource = GetDepts();

        //dgList.ItemsSource = GetUserList();


        //初始化DGVModel
        DGVModel vmodel = new DGVModel();
        vmodel.UserList = GetUserList();
        vmodel.DeptList = GetDepts();

        this.DataContext = vmodel;
}
}

public class UserInfoNew
{
public int UserId { get; set; }
public string UserName { get; set; }
public bool UserState { get; set; }
public int UserAge { get; set; }
public int DeptId { get; set; }
}

public class DeptInfo
{
public int DeptId { get; set; }
public string DeptName { get; set; }
}

/// <summary>
/// Window的数据上下文
/// </summary>
public class DGVModel
{
public List<UserInfoNew> UserList { get; set; }
public List<DeptInfo> DeptList { get; set; }
}

🦋3.2 增删改查案例

以下是一个简单的WPF DataGrid增删改查的案例,其中使用了MVVM的设计模式:

ViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Student> _students;
    public ObservableCollection<Student> Students
    {
        get { return _students; }
        set
        {
            _students = value;
            NotifyPropertyChanged("Students");
        }
    }

    private Student _selectedStudent;
    public Student SelectedStudent
    {
        get { return _selectedStudent; }
        set
        {
            _selectedStudent = value;
            NotifyPropertyChanged("SelectedStudent");
        }
    }

    public MainViewModel()
    {
        Students = new ObservableCollection<Student>
        {
            new Student {Id = 1, Name = "Tom", Gender = "Male", Age = 18},
            new Student {Id = 2, Name = "Lucy", Gender = "Female", Age = 20},
            new Student {Id = 3, Name = "Jack", Gender = "Male", Age = 22}
        };
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Model:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public int Age { get; set; }
}

View:

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

<Grid>
    <DataGrid ItemsSource="{Binding Students}"
              SelectedItem="{Binding SelectedStudent}"
              AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            <DataGridTextColumn Header="Gender" Binding="{Binding Gender}"/>
            <DataGridTextColumn Header="Age" Binding="{Binding Age}"/>
        </DataGrid.Columns>
    </DataGrid>
    <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
        <Button Content="Add" Command="{Binding AddCommand}"/>
        <Button Content="Delete" Command="{Binding DeleteCommand}" Margin="5"/>
        <Button Content="Edit" Command="{Binding EditCommand}"/>
    </StackPanel>
</Grid>

ViewModel中的AddCommand、DeleteCommand、EditCommand:

public ICommand AddCommand => new RelayCommand(() =>
{
    var student = new Student {Id = Students.Count + 1};
    var dialog = new StudentDialog(student);
    if (dialog.ShowDialog() == true)
    {
        Students.Add(student);
    }
});

public ICommand DeleteCommand => new RelayCommand(() =>
{
    if (SelectedStudent != null)
    {
        Students.Remove(SelectedStudent);
    }
});

public ICommand EditCommand => new RelayCommand(() =>
{
    if (SelectedStudent != null)
    {
        var dialog = new StudentDialog(SelectedStudent);
        if (dialog.ShowDialog() == true)
        {
            // 通知DataGrid更新
            var index = Students.IndexOf(SelectedStudent);
            Students.RemoveAt(index);
            Students.Insert(index, SelectedStudent);
        }
    }
});

StudentDialog.xaml:

<Window.DataContext>
    <local:StudentDialogViewModel/>
</Window.DataContext>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <Label Grid.Column="0" Grid.Row="0" Content="ID"/>
    <TextBox Grid.Column="1" Grid.Row="0" Text="{Binding Id}" IsReadOnly="{Binding IsReadOnly}"/>

    <Label Grid.Column="0" Grid.Row="1" Content="Name"/>
    <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Name}" IsReadOnly="{Binding IsReadOnly}"/>

    <Label Grid.Column="0" Grid.Row="2" Content="Gender"/>
    <TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Gender}" IsReadOnly="{Binding IsReadOnly}"/>

    <Label Grid.Column="0" Grid.Row="3" Content="Age"/>
    <TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Age}" IsReadOnly="{Binding IsReadOnly}"/>

    <Button Grid.Column="0" Grid.Row="4" Content="OK" Command="{Binding OKCommand}" Width="60" Margin="5"/>

    <Button Grid.Column="0" Grid.Row="4" Content="Cancel" Command="{Binding CancelCommand}" Width="60" Margin="5"/>
</Grid>

StudentDialogViewModel:

public class StudentDialogViewModel : INotifyPropertyChanged
{
    private Student _student;
    public bool IsReadOnly { get; set; }

    public StudentDialogViewModel()
    {
        OKCommand = new RelayCommand(() => { Close(true); });
        CancelCommand = new RelayCommand(() => { Close(false); });
    }

    public StudentDialogViewModel(Student student)
        : this()
    {
        _student = student;
        if (_student.Id > 0)
        {
            IsReadOnly = true;
        }
    }

    public int Id
    {
        get { return _student.Id; }
        set
        {
            if (_student.Id != value)
            {
                _student.Id = value;
                NotifyPropertyChanged("Id");
            }
        }
    }

    public string Name
    {
        get { return _student.Name; }
        set
        {
            if (_student.Name != value)
            {
                _student.Name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    public string Gender
    {
        get { return _student.Gender; }
        set
        {
            if (_student.Gender != value)
            {
                _student.Gender = value;
                NotifyPropertyChanged("Gender");
            }
        }
    }

    public int Age
    {
        get { return _student.Age; }
        set
        {
            if (_student.Age != value)
            {
                _student.Age = value;
                NotifyPropertyChanged("Age");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public RelayCommand OKCommand { get; set; }
    public RelayCommand CancelCommand { get; set; }

    private void Close(bool result)
    {
        var window = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
        window.DialogResult = result;
        window.Close();
    }
}

StudentDialogViewModel中使用了RelayCommand,这是一个继承自ICommand的自定义命令类,用于绑定按钮的点击事件。

在StudentDialogViewModel中,我们使用了一个私有字段_student来存储传入的Student对象,以及一些属性来绑定StudentDialog的控件,在属性的setter中通知界面更新。

在StudentDialogViewModel中,我们还定义了两个RelayCommand,分别绑定OK和Cancel按钮的点击事件,并在Close方法中关闭窗口并返回结果。

最后,将StudentDialogViewModel传递给StudentDialog.xaml的DataContext,即可实现一个简单的增删改查功能的WPF DataGrid。

🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

在这里插入图片描述

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。