Wpf DataGrid 绑定Dynamic (二维数据表)

Posted 圆滚滚的胖狸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wpf DataGrid 绑定Dynamic (二维数据表)相关的知识,希望对你有一定的参考价值。

最近有一个需求,需要根据用户数据动态生成二维数据表,绑定到表格后,用户再次编辑数据,最后再将编辑过的数据,生成类型数据,存入数据库。

仔细分析过后,觉得最适合的方式,莫过于给DataGrid绑定DynamicObj

以下是项目效果

 二维表格第一行和第一列第二列均于用户以excel的方式传入

然后再进行编辑和选择。然后再将每行数据转为数据库格式。例如某一行数据如下:

 

即Dynamic line数据为:

{
    "parentName": "书法",
    "eventName": "隶书",
    "eventId": 4,
    "G1": "简单",
    "G1-Check": "True",
    "G2": "简单",
    "G2-Check": "False",
    "G3": "",
    "G3-Check": "True",
    "G4": "",
    "G4-Check": "True"

}

根据以上数据,转换为数据库格式

形成数据如下:

[{
        "parentName": "书法",
        "eventName": "隶书",
        "eventId": 4,
        "groupId": 1,
        "remark": "简单"


    },
    {
        "parentName": "书法",
        "eventName": "隶书",
        "eventId": 4,
        "groupId": 3,
        "remark": ""
    },
    {
        "parentName": "书法",
        "eventName": "隶书",
        "eventId": 4,
        "groupId": 4,
        "remark": ""
    }
]

MainWindow.xaml

<Window x:Class="testDataGridBindDynamicObj.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:testDataGridBindDynamicObj"
        mc:Ignorable="d"
        Title="MainWindow" Height="768" Width="1024">
    <Grid>
        <Grid.RowDefinitions >
            <RowDefinition Height="80" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" HorizontalAlignment="Left">
            <Button x:Name="btn_ok" Content="点击" Height="50" Width="92" Margin="458,0" Click="btn_ok_Click" />
        </StackPanel>

        <DataGrid Grid.Row="1"  x:Name="myDataGrid" HorizontalAlignment="Left" Height="474" Margin="10,10,0,0" VerticalAlignment="Top" Width="996" Loaded="myDataGrid_Loaded" />


    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void myDataGrid_Loaded(object sender, RoutedEventArgs e)
        {

            #region Group数据

            List<string> workGroups = new List<string>();
            workGroups.Add("高中组");
            workGroups.Add("初中组");
            workGroups.Add("少儿组");
            workGroups.Add("幼儿组");

            List<WorkGroup> listMatchGroup = new List<WorkGroup>();
            int index = 1;
            workGroups.ForEach(group=> {
                WorkGroup workgroup = new WorkGroup();
                workgroup.MatchGroupId = index;
                workgroup.MatchGroupName = group;
                listMatchGroup.Add(workgroup);
                index++;
            });

            #endregion

            #region Event数据

            List<string> eventInfos = new List<string>();

            eventInfos.Add("正书");
            eventInfos.Add("行书");
            eventInfos.Add("草书");
            eventInfos.Add("隶书");
            eventInfos.Add("篆书");
            eventInfos.Add("石鼓书");
            eventInfos.Add("竹简书");
            eventInfos.Add("乙英");
            eventInfos.Add("曹全");
            eventInfos.Add("张迁");
            eventInfos.Add("一级");
            eventInfos.Add("二级");
            eventInfos.Add("三级");
            eventInfos.Add("自选字体");
            eventInfos.Add("自选内容");
            eventInfos.Add("诗经");
            eventInfos.Add("唐诗");
            eventInfos.Add("宋辞");
            eventInfos.Add("对联");
            eventInfos.Add("其他");



            int eventId = 1;
            List<EventInfo> listEventInfo = new List<EventInfo>();
            eventInfos.ForEach(info => {
                EventInfo infoEvent = new EventInfo();
                infoEvent.EventName = info;
                infoEvent.ParentName = "书法";
                infoEvent.EventId = eventId;
                listEventInfo.Add(infoEvent);
                eventId++;
            });

            #endregion

            #region 设计DataGrid样式(并不是指style)

            //将二维表格样式设计出来

            var typeDtc = new DataGridTextColumn
            {
                Binding = new Binding("parentName"),
                Header = "类别",
                IsReadOnly = true

            };
            myDataGrid.Columns.Add(typeDtc);

            var eventDtc = new DataGridTextColumn
            {
                Binding = new Binding("eventName"),
                Header = "项目名称",
                IsReadOnly = true,
                Width = 100
                
            };
            myDataGrid.Columns.Add(eventDtc);

            var eventIdDtc = new DataGridTextColumn {
                Binding = new Binding("eventId"),
                Visibility = Visibility.Hidden
            };

            listMatchGroup.ForEach(workgroup=> {
                //分组列
                var dtc = new DataGridTextColumn
                {
                    //Binding = new Binding(workgroup.MatchId.ToString()),
                    Binding = new Binding
                    {
                        Path = new PropertyPath($"G{workgroup.MatchGroupId}"),
                        Mode = BindingMode.TwoWay,
                        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                    },
                    Header = workgroup.MatchGroupName,                    
                    Width = 120
                };
                myDataGrid.Columns.Add(dtc);

                //选择列
                //-------------添加选择列       
                //--dgrid为DataGrid实例对象,Row_Checked是响应事件。
                DataGridTemplateColumn dgtc = new DataGridTemplateColumn();
                dgtc.Header = "选择";
                DataTemplate dt = new DataTemplate();
                //定义子元素
                FrameworkElementFactory fef = new FrameworkElementFactory(typeof(CheckBox));
                var binding = new Binding {
                    Path = new PropertyPath($"G{workgroup.MatchGroupId}-Check"),
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                };
                fef.SetValue(CheckBox.IsCheckedProperty, binding);
                fef.SetValue(CheckBox.ForegroundProperty, Brushes.Red);

                //关键部分,为每一项添加事件理解AddHandler的用法      
                //fef.AddHandler(CheckBox.CheckedEvent, new RoutedEventHandler(Cell_Checked));
                //fef.AddHandler(CheckBox.UncheckedEvent, new RoutedEventHandler(Cell_unChecked));
                dt.VisualTree = fef;//添加子元素       
                dgtc.CellTemplate = dt;
                myDataGrid.Columns.Add(dgtc);

            });



            #endregion

            #region 生成dynamic数据源
            // ObservableCollection 为了保证实现数据双向绑定,这样用户数据的输入才可以传递到源中
            ObservableCollection<ExpandoObject> listData = new ObservableCollection<ExpandoObject>();

            //生成数据源,注意key要与之前设计的DataGrid样式绑定中指定的列名保持一至
            listEventInfo.ForEach(infoEvent=> {
                dynamic data = new ExpandoObject();
                (data as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>("parentName",infoEvent.ParentName));
                (data as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>("eventName", infoEvent.EventName));
                (data as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>("eventId", infoEvent.EventId));

                listMatchGroup.ForEach(group => {
                    (data as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>($"G{group.MatchGroupId}", string.Empty));
                    //check数据
                    (data as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>($"G{group.MatchGroupId}-Check", true));
                });
                listData.Add(data);
            });
            #endregion

            #region 绑定数据源
            //将数据源绑定至DataGrid
            myDataGrid.ItemsSource = listData;
            //string line = string.Empty;
            #endregion

        }

       
    }

至此完成。

总结:绑定dynamic比较灵活好用。在此记录一下

附件为项目源码

https://download.csdn.net/download/yexuanbaby/33361276https://download.csdn.net/download/yexuanbaby/33361276

以上是关于Wpf DataGrid 绑定Dynamic (二维数据表)的主要内容,如果未能解决你的问题,请参考以下文章

WPF Datagrid 动态生成列 并绑定数据

如何在 WPF DataGrid 中动态生成列?

WPF入门教程系列二十一——DataGrid示例

wpf datagrid绑定了数据 如果选中多行中怎么获取选中行的某列的值

wpf datagrid 怎么增加数据行

Wpf:如何从嵌套的 DataGrid 中绑定 SelectedItem