WPF-动态生成DataGrid

2020-03-22  本文已影响0人  写前端的大叔

在封装自定义组件的时候,看到很多类似表格的控件,表格中的数据都不是固定的,每个表格的表条和内容都不一样,如果直接在xaml文件中定义DataGrid的话,就显得很麻烦了,可以将期封装成一个动态生成的DataGrid,只需按照一定规则的数据格式,就可以生成表格。如下所示为封装后的一个动态表格:

动态表格.png

1.数据格式

首先来定义一个数据格式,数据格式相对比较简单,只需一个表头字段、内容字段、列宽字段。如下所示:

 public class GridInfo {
        public string name { get; set; }
        public string value { get; set; }
        public int column { get; set; }
    }

2.创建DataGrid

首先创建一个UserControl,然后在里面放入一个DataGrid,并设置样式,如下所示:

<UserControl x:Class="WpfApp1.UCInfoGridColumn"
             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:WpfApp1"
             DataContext="{Binding RelativeSource={RelativeSource Self}}"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <Style TargetType="DataGrid">
            <!--网格线颜色-->
            <Setter Property="CanUserResizeColumns" Value="false"/>
            <Setter Property="BorderBrush" Value="#0668BA" />
            <Setter Property="HorizontalGridLinesBrush">
                <Setter.Value>
                    <SolidColorBrush Color="#0668BA"/>
                </Setter.Value>
            </Setter>
            <Setter Property="VerticalGridLinesBrush">
                <Setter.Value>
                    <SolidColorBrush Color="#0668BA"/>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="SnapsToDevicePixels" Value="True" />
            <Setter Property="Background" Value="White" />
            <Setter Property="FontSize" Value="14" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridColumnHeader">
                        <Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" 
                             BorderBrush="#0668BA" 
                              Width="Auto">
                            <Grid >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <ContentPresenter  Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                <Path x:Name="SortArrow" Visibility="Collapsed" Data="M0,0 L1,0 0.5,1 z" Stretch="Fill"  Grid.Column="2" Width="8" Height="6" Fill="White" Margin="0,0,50,0" 
                            VerticalAlignment="Center" RenderTransformOrigin="1,1" />
                                <Rectangle Width="1" Fill="#0668BA" HorizontalAlignment="Right" Grid.ColumnSpan="1" />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Height" Value="40"/>
        </Style>
        <!--行样式触发-->
        <!--背景色改变必须先设置cellStyle 因为cellStyle会覆盖rowStyle样式-->
        <Style  TargetType="DataGridRow">
            <Setter Property="Background" Value="#344488" />
            <Setter Property="Height" Value="40"/>
            <Setter Property="Foreground" Value="White" />
            <Style.Triggers>
                <!--隔行换色-->
                <Trigger Property="AlternationIndex" Value="0" >
                    <Setter Property="Background" Value="#344488" />
                </Trigger>
                <Trigger Property="AlternationIndex" Value="1" >
                    <Setter Property="Background" Value="#344488" />
                </Trigger>

                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#344488"/>
                </Trigger>

                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="White"/>
                </Trigger>
            </Style.Triggers>
        </Style>

        <!--单元格样式触发-->
        <Style TargetType="DataGridCell">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="DataGridCell">
                        <TextBlock TextAlignment="Center" VerticalAlignment="Center"  >
                           <ContentPresenter />
                        </TextBlock>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="White"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        
    </UserControl.Resources>
    <Border BorderBrush="#0668BA" BorderThickness="1" CornerRadius="3">
        <DataGrid x:Name="dataGrid" HorizontalScrollBarVisibility="Hidden" Foreground="White" Background="#102371"></DataGrid> 
    </Border>
</UserControl>

3.动态生成表格

.cs文件中,添加一个方法,用于传递数据,并根据数据动态生成表格,如下所示:

public void loadData(ObservableCollection<GridInfo> list) {
            if (list == null) {
                return;
            }
            //计算出每一列的宽度
            double width = this.ActualWidth / list.Count;
            dataGrid.Columns.Clear();//每次清空列集合
            for (int i = 0; i < list.Count; i++)
            {
                GridInfo gridInfo = list[i];
                DataGridTextColumn textBoxColumn = new DataGridTextColumn();
                textBoxColumn.Header = gridInfo.name;

                 //定义每一列的宽度相同
                 //textBoxColumn.Width = new DataGridLength(dataGrid.ActualWidth, DataGridLengthUnitType.Star);
                textBoxColumn.Width = width * gridInfo.column;//定义每一列的最小宽度
                Binding binding = new Binding("value");//设置每一列的binding
                //binding.Path = new PropertyPath("name");
                binding.Mode = BindingMode.OneWay;
                textBoxColumn.Binding = binding;
                dataGrid.Columns.Add(textBoxColumn);//将列添加到集合中
            }
            dataGrid.ItemsSource = list;
            dataGrid.AutoGenerateColumns = false;//禁止自动添加列
            dataGrid.CanUserAddRows = false;//禁止自动添加行
            dataGrid.RowHeaderWidth = 0;//去除第一列多余的空白
        }

引入动态表格

创建好表格后,然后再需要地方通过如下方式进行引入:

<local:UCInfoGridColumn  Margin="101,54,0,0" VerticalAlignment="Top" Width="549" x:Name="infoGrid"/>

然后在loaded事件中加入测试数据,来调用loadData方法动态添加表格信息,如下所示:

 private void Page_Loaded(object sender, RoutedEventArgs e)
        {

            ObservableCollection<GridInfo> list = new ObservableCollection<GridInfo>();
            for (int i = 0; i < 3; i++)
            {
                GridInfo column = new GridInfo();
                column.name = "标题" + i;
                column.value = "内容" + i;
                column.column = 1;
                list.Add(column);
            }
            infoGrid.loadData(list);
        }

按以下步骤来做,就可以快速的创建一个自定义的动态表格了。
个人博客

上一篇 下一篇

猜你喜欢

热点阅读