翼度科技»论坛 编程开发 .net 查看内容

一个可以让你有更多时间摸鱼的WPF控件(二)

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
前言
  上文介绍了如何通过一个Form自定义控件来简化数据的录入,并自动实现数据校验,自动布局排列等功能。本文继续介绍如何优化表格控件的使用,缩减代码量,实现工作效率的提升。
一、功能实现
    上文中分析了DataGrid跟ListView两种表格控件的优劣,在这里我们选择ListView来实现我们的表格功能,如有疑问请看上一篇文章,这里不再赘述。
 下面我们定义一个ListViewExtensions静态类来实现ListView的附加属性,并在附加属性更改后实现ListView的优化功能。
  1. public static class ListViewExtensions
  2.     {
  3.         #region AutoGenerateColumns
  4.         public static readonly DependencyProperty AutoGenerateColumnsProperty =
  5.             DependencyProperty.RegisterAttached("AutoGenerateColumns", typeof(bool), typeof(ListViewExtensions), new PropertyMetadata(false, AutoGenerateColumnsChanged));
  6.         public static bool GetAutoGenerateColumns(DependencyObject obj)
  7.         {
  8.             return (bool)obj.GetValue(AutoGenerateColumnsProperty);
  9.         }
  10.         public static void SetAutoGenerateColumns(DependencyObject obj, bool value)
  11.         {
  12.             obj.SetValue(AutoGenerateColumnsProperty, value);
  13.         }
  14.         private static void AutoGenerateColumnsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
  15.         {
  16.             ListView listView = obj as ListView;
  17.             bool autoGenerateColumns = (bool)e.NewValue;
  18.             if (listView != null)
  19.             {
  20.                 if (autoGenerateColumns)
  21.                 {
  22.                     listView.Loaded += ListViewLoadedHandler;
  23.                 }
  24.                 else
  25.                 {
  26.                     listView.Loaded -= ListViewLoadedHandler;
  27.                 }
  28.             }
  29.         }
  30.         private static void ListViewLoadedHandler(object sender, RoutedEventArgs e)
  31.         {
  32.             var listView = (ListView)sender;
  33.             if (listView.ItemsSource == null) return;
  34.             var itemType = listView.ItemsSource.GetType().GetGenericArguments().FirstOrDefault();
  35.             if (itemType != null)
  36.             {
  37.                 // 获取数据源的属性信息
  38.                 var properties = itemType.GetProperties();
  39.                 GridView gridView = null;
  40.                 if (listView.View is GridView gv)
  41.                 {
  42.                     gridView = gv;
  43.                 }
  44.                 else
  45.                 {
  46.                     listView.View = gridView = new GridView();
  47.                 }
  48.                 // 根据属性信息创建列并添加到 GridView 中
  49.                 var optionMappingConverter = new OptionMappingConverter();
  50.                 var enumDescriptionConverter = new EnumDescriptionConverter();
  51.                 foreach (PropertyInfo property in properties)
  52.                 {
  53.                     //排除无用属性
  54.                     var name = property.Name;
  55.                     if (PropertyHelper.IgnoredProperties.Contains(property.Name)) continue;
  56.                     //读取列参数
  57.                     var columnAttribute = property.GetCustomAttributes().OfType<ColumnAttribute>().FirstOrDefault();
  58.                     if (columnAttribute == null || !columnAttribute.IsVisible) continue;
  59.                     //排除重复属性
  60.                     var targetColumn = gridView.Columns.FirstOrDefault(item => GetColumnName(item) == property.Name);
  61.                     if (targetColumn != null)
  62.                     {
  63.                         if (targetColumn.Header == null)
  64.                             targetColumn.Header = columnAttribute.Name;
  65.                         SetColumnIndex(targetColumn, columnAttribute.Order);
  66.                         continue;
  67.                     }
  68.                     var column = new GridViewColumn() { Header = !string.IsNullOrEmpty(columnAttribute.Name) ? columnAttribute.Name : name };
  69.                     SetColumnName(column, property.Name);
  70.                     //分组
  71.                     if (columnAttribute is GroupColumnAttribute group) ListViewExtensions.SetGroup(column, group.Group);
  72.                     //宽度
  73.                     if (columnAttribute.Width > 0) column.Width = columnAttribute.Width;
  74.                     //转换器
  75.                     if (columnAttribute.Converter != null)
  76.                     {
  77.                         column.DisplayMemberBinding = new Binding(property.Name)
  78.                         {
  79.                             Converter = Activator.CreateInstance(columnAttribute.Converter) as IValueConverter,
  80.                             ConverterParameter = columnAttribute.ConverterParameter,
  81.                             StringFormat = columnAttribute.StringFormat
  82.                         };
  83.                     }
  84.                     else
  85.                     {
  86.                         //指定转换器
  87.                         var optionMappingAttribute = property.GetCustomAttributes().OfType<OptionMappingAttribute>().FirstOrDefault();
  88.                         if (optionMappingAttribute != null)
  89.                         {
  90.                             column.DisplayMemberBinding = new Binding(property.Name)
  91.                             {
  92.                                 Converter = optionMappingConverter,
  93.                                 ConverterParameter = optionMappingAttribute.Mapping
  94.                             };
  95.                         }
  96.                         else if (property.PropertyType.IsEnum)
  97.                         {
  98.                             column.DisplayMemberBinding = new Binding(property.Name)
  99.                             {
  100.                                 Converter = enumDescriptionConverter,
  101.                                 StringFormat = columnAttribute.StringFormat
  102.                             };
  103.                         }
  104.                         else
  105.                         {
  106.                             column.DisplayMemberBinding = new Binding(property.Name) { StringFormat = columnAttribute.StringFormat };
  107.                         }
  108.                     }
  109.                     SetColumnIndex(column, columnAttribute.Order);
  110.                     gridView.Columns.Add(column);
  111.                 }
  112.                 var cols = gridView.Columns.OrderBy(item => GetColumnIndex(item)).ToArray();
  113.                 gridView.Columns.Clear();
  114.                 foreach (var col in cols)
  115.                 {
  116.                     gridView.Columns.Add(col);
  117.                 }
  118.             }
  119.         }
  120.         #endregion
  121.         #region ColumnIndex
  122.         public static int GetColumnIndex(DependencyObject obj)
  123.         {
  124.             return (int)obj.GetValue(ColumnIndexProperty);
  125.         }
  126.         public static void SetColumnIndex(DependencyObject obj, int value)
  127.         {
  128.             obj.SetValue(ColumnIndexProperty, value);
  129.         }
  130.         public static readonly DependencyProperty ColumnIndexProperty =
  131.             DependencyProperty.RegisterAttached("ColumnIndex", typeof(int), typeof(ListViewExtensions), new PropertyMetadata(0));
  132.         #endregion
  133.         #region ColumnName
  134.         public static string GetColumnName(DependencyObject obj)
  135.         {
  136.             return (string)obj.GetValue(ColumnNameProperty);
  137.         }
  138.         public static void SetColumnName(DependencyObject obj, string value)
  139.         {
  140.             obj.SetValue(ColumnNameProperty, value);
  141.         }
  142.         public static readonly DependencyProperty ColumnNameProperty =
  143.             DependencyProperty.RegisterAttached("ColumnName", typeof(string), typeof(ListViewExtensions));
  144.         #endregion
  145.         #region Group
  146.         public static string GetGroup(DependencyObject obj)
  147.         {
  148.             return (string)obj.GetValue(GroupProperty);
  149.         }
  150.         public static void SetGroup(DependencyObject obj, string value)
  151.         {
  152.             obj.SetValue(GroupProperty, value);
  153.         }
  154.         public static readonly DependencyProperty GroupProperty =
  155.             DependencyProperty.RegisterAttached("Group", typeof(string), typeof(ListViewExtensions));
  156.         #endregion
  157.     }
复制代码
二、示例代码
View
  1. [/code][b]Model[/b]
  2. [code] public class Person : ValidationObjectBase
  3.     {
  4.         private string _name;
  5.         private DateTime _dateOfBirth = DateTime.Now;
  6.         private int _age;
  7.         private int _gender = 1;
  8.         private string _phoneNumber;
  9.         private string _email;
  10.         private string _address;
  11.         private string _idCardNumber;
  12.         private EducationInfo _education;
  13.         private MaritalStatus _maritalStatus;
  14.         /// <summary>
  15.         /// 姓名
  16.         /// </summary>
  17.         [Column(Name = "姓名", Order = 1)]
  18.         public string Name
  19.         {
  20.             get => _name;
  21.             set => this.SetProperty(ref _name, value);
  22.         }
  23.         /// <summary>
  24.         /// 出生日期
  25.         /// </summary>
  26.         [Column(Name = "出生日期", StringFormat = "{0:yyyy年MM月dd日}", Order = 2)]
  27.         public DateTime DateOfBirth
  28.         {
  29.             get => _dateOfBirth;
  30.             set => this.SetProperty(ref _dateOfBirth, value);
  31.         }
  32.         /// <summary>
  33.         /// 年龄
  34.         /// </summary>
  35.         [Column(Name = "年龄", Order = 3)]
  36.         public int Age
  37.         {
  38.             get => _age;
  39.             set => this.SetProperty(ref _age, value);
  40.         }
  41.         /// <summary>
  42.         /// // 性别
  43.         /// </summary>
  44.         [Column(Name = "性别", Order = 4)]
  45.         public int Gender
  46.         {
  47.             get => _gender;
  48.             set => this.SetProperty(ref _gender, value);
  49.         }
  50.         /// <summary>
  51.         /// 手机号码
  52.         /// </summary>
  53.         [Column(Name = "电话号码", Order = 5)]
  54.         public string PhoneNumber
  55.         {
  56.             get => _phoneNumber;
  57.             set => this.SetProperty(ref _phoneNumber, value);
  58.         }
  59.         /// <summary>
  60.         /// 电子邮箱
  61.         /// </summary>
  62.         [Column(Name = "电子邮箱", Order = 6)]
  63.         public string Email
  64.         {
  65.             get => _email;
  66.             set => this.SetProperty(ref _email, value);
  67.         }
  68.         /// <summary>
  69.         /// 地址信息
  70.         /// </summary>
  71.         [Column(Name = "地址", Order = 7)]
  72.         public string Address
  73.         {
  74.             get => _address;
  75.             set => this.SetProperty(ref _address, value);
  76.         }
  77.         /// <summary>
  78.         /// 身份证号码
  79.         /// </summary>
  80.         [Column(Name = "身份证号码", Order = 8)]
  81.         public string IdCardNumber
  82.         {
  83.             get => _idCardNumber;
  84.             set => this.SetProperty(ref _idCardNumber, value);
  85.         }
  86.         /// <summary>
  87.         /// 教育信息
  88.         /// </summary>
  89.         //[Column(Name = "教育信息", IsVisible = false, Order = 9)]
  90.         public EducationInfo Education
  91.         {
  92.             get => _education;
  93.             set => this.SetProperty(ref _education, value);
  94.         }
  95.         /// <summary>
  96.         /// 婚姻状况
  97.         /// </summary>
  98.         [Column(Name = "婚姻状况", Order = 10)]
  99.         public MaritalStatus MaritalStatus
  100.         {
  101.             get => _maritalStatus;
  102.             set => this.SetProperty(ref _maritalStatus, value);
  103.         }<br>}
复制代码
ViewModel
  1. public class FormDemoViewModel : BindableBase
  2.     {
  3.         public ObservableCollection<Person> Collection
  4.         {
  5.             get { return _collection; }
  6.             set { this.SetProperty(ref _collection, value); }
  7.         }
  8.     }
复制代码

 三、答疑解惑
2.1 如何添加自定义列?
答:可以按常规方式添加自定义列,用ListViewExtensions.ColumnIndex来指定位的位置,以下为示例代码。
  1. <ListView extensions:ListViewExtensions.AutoGenerateColumns="True" ItemsSource="{Binding Collection}">
  2.     <GridView>
  3.         <GridViewColumn extensions:ListViewExtensions.ColumnIndex="0">
  4.             <GridViewColumn.Header>
  5.                 <CheckBox Content="全选" />
  6.             </GridViewColumn.Header>
  7.             <GridViewColumn.CellTemplate>
  8.                 <DataTemplate>
  9.                     <CheckBox />
  10.                 </DataTemplate>
  11.             </GridViewColumn.CellTemplate>
  12.         </GridViewColumn>
  13.     </GridView>
  14. </ListView>
复制代码
2.2 如何自动生成的列不满足需求,可不可以自己定义列?
答:可以,使用ListViewExtensions.ColumnName属性可以覆盖某一个列的自动生成的操作。
  1. <ListView extensions:ListViewExtensions.AutoGenerateColumns="True" ItemsSource="{Binding Collection}">
  2.     <GridView>
  3.         <GridViewColumn
  4.                     extensions:ListViewExtensions.ColumnIndex="1"
  5.                     extensions:ListViewExtensions.ColumnName="Name">
  6.             <GridViewColumn.CellTemplate>
  7.                 <DataTemplate>
  8.                     <TextBlock Text="{Binding Name}" />
  9.                 </DataTemplate>
  10.             </GridViewColumn.CellTemplate>
  11.         </GridViewColumn>
  12.     </GridView>
  13. </ListView>
复制代码
2.3 如何给列设置顺序?
答:在属性上给ColumnAttribute特性设置参数Order。
  1. [Column(Name = "出生日期", Order = 2)]
  2. public DateTime DateOfBirth
  3. {
  4.       get => _dateOfBirth;
  5.       set => this.SetProperty(ref _dateOfBirth, value);
  6. }
复制代码
2.4 如何设置列的宽度?
答:在属性上给ColumnAttribute特性设置参数Width。
  1. [Column(Name = "出生日期", Width =100)]
  2. public DateTime DateOfBirth
  3. {
  4.       get => _dateOfBirth;
  5.       set => this.SetProperty(ref _dateOfBirth, value);
  6. }
复制代码
2.5 如何将列设为不可见?
答:在属性上给ColumnAttribute特性设置参数IsVisible。
  1. [Column(Name = "出生日期", IsVisible = false)]
  2. public DateTime DateOfBirth
  3. {
  4.        get => _dateOfBirth;
  5.        set => this.SetProperty(ref _dateOfBirth, value);
  6. }
复制代码
2.6 如何给绑定设置格式化字符串?
答:在属性上给ColumnAttribute特性设置参数StringFormat。
  1. [Column(Name = "出生日期", StringFormat = "{0:yyyy年MM月dd日}")]
  2. public DateTime DateOfBirth
  3. {
  4.       get => _dateOfBirth;
  5.       set => this.SetProperty(ref _dateOfBirth, value);
  6. }
复制代码
2.7 如何给绑定设置转换器及参数?
答:在属性上给ColumnAttribute特性设置Converter和ConverterParameter参数。
  1. [Column(Name = "出生日期", Converter = typeof(TestConverter), ConverterParameter=1)]
  2. public DateTime DateOfBirth
  3. {
  4.       get => _dateOfBirth;
  5.       set => this.SetProperty(ref _dateOfBirth, value);
  6. }
复制代码
 

来源:https://www.cnblogs.com/qushi2020/p/18106033
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具