WPF 数据集合绑定到DataGrid、ListView或者其他列表控件

需求描述

需要使用一个类似表格的控件,数据格式如下:

数据名称 数据标记 数据值选择
DataA true Kea(可选的值:Kea,Lau,Nuh)
DataB true Lau(可选的值:Kea,Lau,Nuh)
DataC true invalid(可选的值:invalid,valid)
DataD false invalid(可选的值:invalid,valid)
DataE true 0(可选的值:0,1,2,3,4,5,6)
DataF true 100(可选的值:0,20,40,60,80,100,120,140,160,180,200)
DataG true 3(可选的值:0,1,2,3,4,5,6)

 

 

需求分析

  • 界面实现分析:

    可以看出,我们的数据排列为:名称、标识和值。名称可以通过TextBlock之类的标签控件实现,标识可以使用CheckBox或者ToggleButton实现;最后的值典型的需要使用下拉列表框(ComboBoxListBox等)。

    能够实现以上布局的有:①表格(DataGrid);②列表(ListBoxListViewItemControl);③自定义控件布局(数据有限和确定的情况下可以考虑)。本次对前两种进行讨论。

    DataGrid具备行、列的形式,因此很容易想到。每列我们分别使用DataGridTextColumnDataGridCheckBoxColumnDataGridComboBoxColumn即可完成。

    列表典型的列结构,不伦我们使用哪种列表,都需要自定义一个数据模板,用以实现我们

  • 数据结构分析:

    我们数据其实非常有规律,可以将其结构定义如下:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace Melphi.UiCore
{
    /// 
    /// ListViewsView.xaml 的交互逻辑
    /// 
    public partial class ListViewsView : UserControl
    {
        public ListViewsView()
        {
            InitializeComponent();
        }

        private ObservableCollection melphiDataSource = new ObservableCollection();

        /// 
        /// 数据源
        /// 
        public ObservableCollection MelphiDataSource
        {
            get
            {
                return melphiDataSource;
            }
            set
            {
                melphiDataSource = value;
            }
        }
    }

    /// 
    /// 数据项
    /// 
    public class MelphiDataItem
    {
        /// 
        /// 数据名称
        /// 
        public string Name { get; set; }

        /// 
        /// 数据标识
        /// 
        public bool IsEnabled { get; set; }

        /// 
        /// 设定值
        /// 
        public string SelectedValue { get; set; }

        /// 
        /// 设定值选定项集合
        /// 
        public List SelectionSource { get; set; }

    }
}

稍做说明:每个数据项就是一个MelphiDataItem的实例,使用变化自动通知界面的集合ObservableCollection来存储所有的数据。

 

设计实现

  • 初始化数据

一般情况下,我们的数据获取来源一般由文件、服务器或者数据库获得,为了方便,这里就直接在程序里面定义了。

public class MelphiDataService
    {
        /// 
        /// 模拟获取数据源
        /// 
        /// 
        public static ObservableCollection GetDataSource()
        {
            ObservableCollection melphiDatas = new ObservableCollection();
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataA",
                IsEnabled = true,
                SelectedValue = "Kea",
                SelectionSource = new List() { "Kea", "Lau", "Nuh" }
            });
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataB",
                IsEnabled = true,
                SelectedValue = "Lau",
                SelectionSource = new List() { "Kea", "Lau", "Nuh" }
            });
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataC",
                IsEnabled = true,
                SelectedValue = "invalid",
                SelectionSource = new List() { "invalid", "valid" }
            });
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataD",
                IsEnabled = true,
                SelectedValue = "invalid",
                SelectionSource = new List() { "invalid", "valid" }
            });
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataE",
                IsEnabled = false,
                SelectedValue = "0",
                SelectionSource = new List() { "0", "1", "2", "3", "4", "5", "6" }
            });
​
            var listsource = new List();
            for (int i = 0; i <= 200; i+=20)
            {
                listsource.Add(i.ToString());
            }
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataF",
                IsEnabled = true,
                SelectedValue = "100",
                SelectionSource = listsource
            });
​
            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataG",
                IsEnabled = true,
                SelectedValue = "3",
                SelectionSource = new List() { "0", "1", "2", "3", "4", "5", "6" }
            });
​
            return melphiDatas;
        }
    }

在程序视图构造时获取数据,并将数据复制给我们界面绑定的数据源。

public partial class ListViewsView : UserControl
    {
        public ListViewsView()
        {
            InitializeComponent();

            // 获取数据源
            MelphiDataSource = MelphiDataService.GetDataSource();
        }

        private ObservableCollection melphiDataSource = new ObservableCollection();

        /// 
        /// 数据源
        /// 
        public ObservableCollection MelphiDataSource
        {
            get
            {
                return melphiDataSource;
            }
            set
            {
                melphiDataSource = value;
            }
        }
    }
using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace Melphi.UiCore
{
    /// 
    /// DataGridsView.xaml 的交互逻辑
    /// 
    public partial class DataGridsView : UserControl
    {
        public DataGridsView()
        {
            InitializeComponent();

            // 获取数据源
            MelphiDataSource = MelphiDataService.GetDataSource();
        }

        private ObservableCollection melphiDataSource = new ObservableCollection();

        /// 
        /// 数据源
        /// 
        public ObservableCollection MelphiDataSource
        {
            get
            {
                return melphiDataSource;
            }
            set
            {
                melphiDataSource = value;
            }
        }
    }
}
  • 界面设计以及数据绑定

  • ListView

    
        
            
                
                
                    
                        
                            
                                
                                    
                                    
                                    
                                

                                

                                
                                    
                                
                                

                            
                        
                    
                
                
                
                    
                        
                            
                                
                                    
                                        
                                        
                                        
                                    

                                    

                                    
                                        
                                        
                                        
                                    

                                    
                                    
                                
                            
                        
                    
                
            

        
    
  • DataGrid


    
        
            
                
                    
                        
                            
                                
                                    
                                    
                                
                            
                        
                    
                
                
                    
                    
                    
                    
                    
                        
                            
                                
                            
                        
                    

                    
                    
                    
                        
                            
                        
                        
                            
                        
                    
                
            
        
    

注意:

1.使用DataGridComboBoxColumn作为数据列时,需要修改DataGridComboBoxColumnEditingElementStyleElementStyle,将我们数据绑定到这两个样式上的ItemsSourceSelectedValue上。如果直接绑定到DataGridComboBoxColumnItemsSourceSelectedValue上,我们的数据绑定是无效的。

2.DataGrid控件提供的列中,有一个非常方便的列控件——DataGridTemplateColumn。这个模板列控件可以按照我们的界面需求进行自定义界面样式和数据绑定。值得留意的是:DataGrid提供的默认列,如DataGridTextColumnDataGridCheckBoxColumnDataGridComboBoxColumn以及DataGridHyperlinkColumn在做数据绑定时,默认情况下数据绑定是双向更新的(数据模型<-->界面);但是DataGridTemplateColumn的默认绑定是单向的(数据模型-->界面),如果需要双向时,需要对绑定的数据 指定UpdateSourceTrigger,如下所示,而列表类的控件就没有这个细节。

 
 
     
         
             
         
     
 
  • 运行调试

WPF 数据集合绑定到DataGrid、ListView或者其他列表控件_第1张图片WPF 数据集合绑定到DataGrid、ListView或者其他列表控件_第2张图片WPF 数据集合绑定到DataGrid、ListView或者其他列表控件_第3张图片

 

总结

虽然完成之后觉得很简单没什么,但是我在最开始拿到需求到真正实现的过程中走了不少的弯路,从早上上班到下午3点才算解决。

现在回头,觉得自己之所以走弯路,主要的问题出现在对控件的不熟悉,其中DataGridDataGridComboBoxColumn数据绑定不成功耗费最多。其次是对自己定义的数据结构不信任,导致对数据结构的多次更换、重新实验。

还是列表控件拯救了我,相比DataGrid控件,自己对列表控件认识要更深一些(也许是他更简单一些吧),让我最终坚信我的数据结构没问题,"简单轻松"得完成了需求。

但是DataGrid控件确实是一个非常好的控件。我们可以看到他具备一些普通的列模板,虽然不能完全满足我们的需求。但是他提供了DataGridTemplateColumn列模板,我们可以根据我们的界面和数据需求进行自制模板。是不是很nice。不仅如此,该控件还提供了很多额外的功能,一般的编辑功能就不说了,还有选中提示功能如RowDetailsTemplate中定义了我们点击某一行时,的提示模板......总之,非常强,早学早轻松。

最后再说一点,在程序开发时,我们需要分析,尤其是对数据结构的分析,慢慢地你会得到极大提升。

 

 

你可能感兴趣的:(C#,WPF)