WPF(DataGid学习)

先看两张图,一个实现自己的效果,一个使用默认的效果:

 

GitHub地址 https://github.com/Bridge2018/WPF-DataGridhttps://github.com/Bridge2018/WPF-DataGrid


 不多说,上代码。。。

1.转换器

因为里面有个DateTime,要通过转换器转换为对应的字符串。

using System;
using System.Globalization;
using System.Windows.Data;

[ValueConversion(typeof(DateTime), typeof(string))]
public class DateConverter : IValueConverter
{
    public string Format { get; set; } = "yyyy-MM-dd HH:mm:ss.fff";

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        DateTime dt = (DateTime)value;
        return dt.ToString(Format);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return DateTime.Parse(value.ToString());
    }
}

2.资源字典 

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfApp6">

    <FontFamily x:Key="iconFont">/WpfApp6;component/fonts/iconfont/#iconfont</FontFamily>
    <FontFamily x:Key="songti">宋体</FontFamily>
    <SolidColorBrush x:Key="mainBackground" Color="#B0E2FF" />

    <local:DateConverter x:Key="dataConverterFull" />
    <local:DateConverter x:Key="dataConverterShort" Format="yyyy-MM-dd HH:mm:ss" />

</ResourceDictionary>

为了实现两个CheckBox的效果,用到了iconFont图标字体 https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.5&type=1https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.5&type=1

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/WpfApp6;component/DictionaryUse.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <Style TargetType="CheckBox" x:Key="ckColumn">
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="VerticalAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="{StaticResource iconFont}" />
        <Setter Property="FontSize" Value="25" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="CheckBox">
                    <Border Background="Transparent">
                        <TextBlock x:Name="tb" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontWeight="{TemplateBinding FontWeight}" Foreground="Black" Text="{TemplateBinding Content}" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter TargetName="tb" Property="Text" Value="{Binding Tag, RelativeSource={RelativeSource AncestorType=CheckBox}}" />
                            <Setter TargetName="tb" Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType=CheckBox}}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="TextBlock" x:Key="tbColumn">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="TextWrapping" Value="WrapWithOverflow" />
    </Style>

    <Style TargetType="DataGridColumnHeader" x:Key="gridColHeaderStyle">
        <Setter Property="Background" Value="#4F94CD" />
        <Setter Property="FontFamily" Value="{StaticResource songti}" />
        <Setter Property="FontSize" Value="18" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Padding" Value="8" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridColumnHeader">
                    <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}">
                        <TextBlock HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Text="{TemplateBinding Content}" TextAlignment="Center" TextWrapping="Wrap" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="DataGridCell" x:Key="gridCellStyle">
        <Setter Property="VerticalAlignment" Value="Stretch" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="#FFDEAD" />
                <Setter Property="Foreground" Value="Black" />
                <Setter Property="BorderThickness" Value="0" />
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style TargetType="DataGridRow" x:Key="gridRowStyle">
        <Setter Property="Background" Value="White" />
        <Setter Property="Height" Value="35" />
        <Setter Property="FontSize" Value="18" />
        <!--<Setter Property="BorderThickness" Value="2"/>
        <Setter Property="BorderBrush" Value="Red"/>-->
        <Style.Triggers>
            <Trigger Property="AlternationIndex" Value="1">
                <Setter Property="Background" Value="#87CEFF" />
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="#EEA9B8" />
                <Setter Property="BorderThickness" Value="0,2,0,2" />
                <Setter Property="BorderBrush" Value="Black" />
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="FontSize" To="20" Duration="0:0:0.3" />
                            <DoubleAnimation Storyboard.TargetProperty="Height" To="37" Duration="0:0:0.3" />
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="FontSize" Duration="0:0:0.2" />
                            <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.3" />
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style TargetType="DataGrid" x:Key="gridStyle">
        <!--<Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />-->
        <Setter Property="AlternationCount" Value="2" />
        <Setter Property="AutoGenerateColumns" Value="False" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="CanUserAddRows" Value="False" />
        <Setter Property="CanUserReorderColumns" Value="False" />
        <Setter Property="CanUserResizeColumns" Value="False" />
        <Setter Property="CanUserResizeRows" Value="False" />
        <Setter Property="CanUserSortColumns" Value="False" />
        <Setter Property="GridLinesVisibility" Value="None" />
        <!--<Setter Property="VirtualizingPanel.IsVirtualizing" Value="False" />-->
        <Setter Property="RowHeaderWidth" Value="0" />
        <Setter Property="ColumnHeaderStyle" Value="{StaticResource gridColHeaderStyle}" />
        <Setter Property="CellStyle" Value="{StaticResource gridCellStyle}" />
        <Setter Property="RowStyle" Value="{StaticResource gridRowStyle}" />
    </Style>

</ResourceDictionary>

3.视图模型

namespace WpfApp6
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Collections.ObjectModel;
    using System.ComponentModel;

    public class ProgramListViewModel
    {
        public ObservableCollection<ProgramStepModel> ProgramModels { get; set; } = new ObservableCollection<ProgramStepModel>();

        public bool CanEdit { get; set; } = true;

        public ProgramListViewModel()
        {
            Random random = new Random();
            for (int i = 0; i < 30; i++)
            {
                ProgramModels.Add(new ProgramStepModel { IsQuick = random.Next(2) == 0, Num = i + 1, Name = Tools.RandomName(5, 8), AlterTime = DateTime.Now, IsLock = random.Next(2) == 0 });
            }
        }
    }

    public class ProgramStepModel
    {
        public bool IsQuick { get; set; }

        public int Num { get; set; }

        public string Name { get; set; }

        public Sex Sex { get; set; }

        public DateTime AlterTime { get; set; }

        public bool IsLock { get; set; }

        public override string ToString()
        {
            return $"IsQuick:{IsQuick}  Num:{Num}  Name:{Name}  AlterTime:{AlterTime}  IsLock:{IsLock}";
        }

    }

    public enum Sex
    {
        Man,
        Woman,
    }

    public class Tools
    {
        static Random Random = new Random();
        public static string RandomName(int minLen, int maxLen, bool haveNum = true)
        {
            List<int> listAscii = new List<int>();
            if (haveNum)
            {
                listAscii.AddRange(Enumerable.Range(48, 10));
            }
            listAscii.AddRange(Enumerable.Range(65, 26));
            listAscii.AddRange(Enumerable.Range(97, 26));
            return Encoding.ASCII.GetString(listAscii.ConvertAll(t => (byte)t).OrderBy(l => Guid.NewGuid()).Take(Random.Next(minLen, maxLen)).ToArray());
        }
    }
}

4.窗体XAML

<Window x:Class="WpfApp6.MainWindow" Title="MainWindow" 
        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:WpfApp6"
        xmlns:core="clr-namespace:System;assembly=mscorlib" 
        Width="1000" Height="600" mc:Ignorable="d">
    <Window.DataContext>
        <local:ProgramListViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.Resources>
            <ObjectDataProvider x:Key="myEnum" MethodName="GetValues" ObjectType="{x:Type core:Enum}">
                <ObjectDataProvider.MethodParameters>
                    <x:Type Type="local:Sex" />
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <DataGrid x:Name="grid" AutoGenerateColumns="False" CanUserAddRows="True" ItemsSource="{Binding ProgramModels}" Style="{StaticResource gridStyle}">
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="0.1*" Header="快捷" IsReadOnly="True">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox Content="&#xe64d;" Foreground="#00B2EE" IsChecked="{Binding IsQuick, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                      IsEnabled="{Binding DataContext.CanEdit, RelativeSource={RelativeSource AncestorType=Window}}" Style="{StaticResource ckColumn}" Tag="&#xe64e;" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTextColumn Width="0.1*" Binding="{Binding Num}" ElementStyle="{StaticResource tbColumn}" Header="序号" IsReadOnly="True" />
                <DataGridTextColumn Width="0.3*" Binding="{Binding Name}" ElementStyle="{StaticResource tbColumn}" Header="名称" />
                <DataGridComboBoxColumn Width="0.1*" Header="性别" ItemsSource="{Binding Source={StaticResource myEnum}}" SelectedItemBinding="{Binding Sex}">
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="HorizontalAlignment" Value="Center" />
                            <Setter Property="VerticalAlignment" Value="Center" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                </DataGridComboBoxColumn>
                <DataGridTextColumn Width="0.2*" Binding="{Binding AlterTime, Converter={StaticResource dataConverterShort}}" ElementStyle="{StaticResource tbColumn}" Header="修改时间" IsReadOnly="True" />

                <DataGridTemplateColumn Width="0.1*" Header="锁定" IsReadOnly="True">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox Content="&#xe85a;" FontSize="28" FontWeight="Bold" Foreground="#EE7600" IsChecked="{Binding IsLock, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                      IsEnabled="{Binding DataContext.CanEdit, RelativeSource={RelativeSource AncestorType=Window}}" Style="{StaticResource ckColumn}" Tag="&#xe85e;" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

5.DataGrid属性 

  •  AutoGenerateColumns 获取或设置一个值,该值指示是否自动创建列。当设置为True时(默认为True),会根据ItemsSource自动创建列;若同时手动创建时,先显示自动创建的列再显示手动创建的列。
  • AlternationCount 获取或设置 ItemsControl 中的交替项容器的数目,该控件可使交替容器具有唯一外观。例如:若是设置为3,那么每行的AlternationIndex就是按照 0,1,2,0,1,2...这样排序,我们就可以通过触发器设置对应行的样式了。
  • GridLinesVisibility 指示显示哪些网格线,可以不显示,或者显示竖线、横线
  • HeadersVisibility 指定行和列标题的可见性的值。
  • EnableRowVirtualization、EnableColumnVirtualization 是否启用虚拟化,默认是启动的,仅在需要时才会创建对象,并尽可能多地重用它们。启用后若是获取未正在显示的行会出异常。
  • DataGrid目前支持下面这集中类型的列:
    DataGridTextColumn文本类型,在TextBlock元素中显示
    DataGridCheckBoxColumn复选框
    DataGridHyperlinkColumn可单击的链接
    DataGridComboxBox可下拉的ComboBox控件
    DataGridTemplateColumn这种列允许自定义数据模板
  • 每个列都有ElementStyle(未处于编辑模式的单元格显示的样式)和EditingElementStyle(呈现的列将显示处于编辑模式下的样式)。

  • 只有在编辑模式下修改数据才有效,其他几个类型的列在非编辑模式下是无法修改数据的,但是DataGridCheckBoxColumn可以在非编辑模式下修改,只是显示效果上而已,并不能真正意义上改变了数据,所以当我们设计时要注意这一点。

  • 可以通过设置每列的IsReadOnly来控制列信息是否可以修改,但是对于DataGridTemplateColumn无效,需要自行定义变量控制是否可以修改 


6.DataGrid样式 

通过上面的资源字典可以发现,这里我只对DataGrid中的三个属性设置了对应的样式: 

<Setter Property="ColumnHeaderStyle" Value="{StaticResource gridColHeaderStyle}" />
<Setter Property="CellStyle" Value="{StaticResource gridCellStyle}" />
<Setter Property="RowStyle" Value="{StaticResource gridRowStyle}" />
RowHeaderStyle获取或设置应用于所有行标题的样式。TargetType="DataGridRowHeader"
ColumnHeaderStyle获取或设置应用于中的所有列标题的样式 TargetType="DataGridColumnHeader"
RowStyle获取或设置应用到的所有行的样式。TargetType="DataGridRow"
CellStyle获取或设置应用于中的所有单元格的样式 TargetType="DataGridCell"
DropLocationIndicatorStyle获取或设置用于指示何时拖动列标题的放置位置的样式。
DragIndicatorStyle获取或设置呈现拖动指示器显示同时拖动列标题时使用的样式。

7.DataGrid相关事件 

 LoadingRowUnloadingRow

private void grid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    DataGrid dataGrid = sender as DataGrid;
    DataGridRow row = e.Row;
    FrameworkElement cellContent = dataGrid.Columns[0].GetCellContent(row);
    if (cellContent != null)
    {
        ProgramStepModel stepModel = row.Item as ProgramStepModel;
        if (stepModel.IsLock)
        {
            DataGridCell gridCell = dataGrid.Columns[5].GetCellContent(row.Item).Parent as DataGridCell;
            gridCell.Background = new SolidColorBrush(Colors.Red);
        }
    }
}

当我们如上述这样订阅事件,当IsLock为True时将对于的Cell背景色设置为红色。

  • EnableRowVirtualization为false时,cellContent一直为null,所以就不能达到效果;
  • EnableRowVirtualization为true时,运行后会发现当前已显示的行没有效果,但是当我们滚动行时,加载未显示的行,这些行是可以实现效果的。

此事件使您能够在重复使用行之前对该行进行任何必要的更改。 通常使用LoadingRow事件来撤消在事件处理程序中进行的任何更改;若要在重新使用行之前撤消这些自定义项,请处理 UnloadingRow 事件。 

DataGridRow_MouseLeftButtonDown、DataGridRow_MouseDoubleClick 

和行相关的鼠标事件需要在RowStyle中定义:

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow" BasedOn="{StaticResource gridRowStyle}">
        <EventSetter Event="MouseDoubleClick" Handler="DataGridRow_MouseDoubleClick"/>
        <EventSetter Event="MouseLeftButtonDown" Handler="DataGridRow_MouseLeftButtonDown"/>
    </Style>
</DataGrid.RowStyle>
private void DataGridRow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataGridRow row = sender as DataGridRow;
}

 PS:行的Selected和UnSelected事件和触发器也是在RowStyle中定义,需要注意的是在该样式中设置选中行的背景色是无效,需要单独设置每个单元格的样式才有效。

 DataGridCell_MouseLeftButtonDown、DataGridCell_MouseDoubleClick

和单元各相关的鼠标事件需要在CellStyle中定义: 

<DataGrid.CellStyle>
    <Style TargetType="DataGridCell" BasedOn="{StaticResource gridCellStyle}">
        <EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>
        <EventSetter Event="MouseLeftButtonDown" Handler="DataGridCell_MouseLeftButtonDown"/>
    </Style>
</DataGrid.CellStyle>
 private void DataGridCell_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
     DataGridCell dataGridCell = sender as DataGridCell;
     dataGridCell.Background = new SolidColorBrush(Colors.Gold);
 }

PS:单元格的Selected和UnSelected事件和触发器也是在CellStyle中定义。

<Style TargetType="DataGridCell" x:Key="gridCellStyle">
    <Setter Property="VerticalAlignment" Value="Stretch" />
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="#FFDEAD" />
            <Setter Property="Foreground" Value="Black" />
            <Setter Property="BorderThickness" Value="0" />
        </Trigger>
    </Style.Triggers>
</Style>

8.DataGrid数据获取 

若是我们不是在DataGrid相关事件中如何获取DataGrid的每行,每列和每个单元格呢???

获取列

  •  ObservableCollection<DataGridColumn> columns = this.grid.Columns; 然后通过索引就可以获取对应的列
  • DataGridColumn col0 = this.grid.ColumnFromDisplayIndex(0); 直接调用方法获取对于索引的列

获取行 

 通过ItemsControl的ItemContainerGenerator对象获取对应的行:

  • DataGridRow row0 = this.grid.ItemContainerGenerator.ContainerFromIndex(0) as DataGridRow;
  • DataGridRow row0 = this.grid.ItemContainerGenerator.ContainerFromItem(this.grid.Items[0]) as DataGridRow;

获取单元格 

 获取单元格需要先获取行和列:

  • DataGridRow row0 = this.grid.ItemContainerGenerator.ContainerFromIndex(0) as DataGridRow;
    DataGridColumn col0 = this.grid.ColumnFromDisplayIndex(0);
    DataGridCell cell = col0.GetCellContent(row0).Parent as DataGridCell; 
  • DataGridColumn col0 = this.grid.ColumnFromDisplayIndex(0);
    DataGridCell cell = col0.GetCellContent(this.grid.Items[0]).Parent as DataGridCell;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bridge_go

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值