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

  • 一个可以让你有更多时间摸鱼的WPF控件(二)已关闭评论
  • 21 次浏览
  • A+
所属分类:.NET技术
摘要

前言   上文介绍了如何通过一个Form自定义控件来简化数据的录入,并自动实现数据校验,自动布局排列等功能。本文继续介绍如何优化表格控件的使用,缩减代码量,实现工作效率的提升。

前言

  上文介绍了如何通过一个Form自定义控件来简化数据的录入,并自动实现数据校验,自动布局排列等功能。本文继续介绍如何优化表格控件的使用,缩减代码量,实现工作效率的提升。

一、功能实现

    上文中分析了DataGrid跟ListView两种表格控件的优劣,在这里我们选择ListView来实现我们的表格功能,如有疑问请看上一篇文章,这里不再赘述。

 下面我们定义一个ListViewExtensions静态类来实现ListView的附加属性,并在附加属性更改后实现ListView的优化功能。

public static class ListViewExtensions     {         #region AutoGenerateColumns         public static readonly DependencyProperty AutoGenerateColumnsProperty =             DependencyProperty.RegisterAttached("AutoGenerateColumns", typeof(bool), typeof(ListViewExtensions), new PropertyMetadata(false, AutoGenerateColumnsChanged));          public static bool GetAutoGenerateColumns(DependencyObject obj)         {             return (bool)obj.GetValue(AutoGenerateColumnsProperty);         }          public static void SetAutoGenerateColumns(DependencyObject obj, bool value)         {             obj.SetValue(AutoGenerateColumnsProperty, value);         }          private static void AutoGenerateColumnsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)         {             ListView listView = obj as ListView;             bool autoGenerateColumns = (bool)e.NewValue;              if (listView != null)             {                 if (autoGenerateColumns)                 {                     listView.Loaded += ListViewLoadedHandler;                  }                 else                 {                     listView.Loaded -= ListViewLoadedHandler;                 }             }         }          private static void ListViewLoadedHandler(object sender, RoutedEventArgs e)         {             var listView = (ListView)sender;             if (listView.ItemsSource == null) return;              var itemType = listView.ItemsSource.GetType().GetGenericArguments().FirstOrDefault();             if (itemType != null)             {                 // 获取数据源的属性信息                 var properties = itemType.GetProperties();                 GridView gridView = null;                 if (listView.View is GridView gv)                 {                     gridView = gv;                 }                 else                 {                     listView.View = gridView = new GridView();                 }                  // 根据属性信息创建列并添加到 GridView 中                 var optionMappingConverter = new OptionMappingConverter();                 var enumDescriptionConverter = new EnumDescriptionConverter();                 foreach (PropertyInfo property in properties)                 {                     //排除无用属性                     var name = property.Name;                     if (PropertyHelper.IgnoredProperties.Contains(property.Name)) continue;                      //读取列参数                     var columnAttribute = property.GetCustomAttributes().OfType<ColumnAttribute>().FirstOrDefault();                     if (columnAttribute == null || !columnAttribute.IsVisible) continue;                      //排除重复属性                     var targetColumn = gridView.Columns.FirstOrDefault(item => GetColumnName(item) == property.Name);                     if (targetColumn != null)                     {                         if (targetColumn.Header == null)                             targetColumn.Header = columnAttribute.Name;                         SetColumnIndex(targetColumn, columnAttribute.Order);                         continue;                     }                      var column = new GridViewColumn() { Header = !string.IsNullOrEmpty(columnAttribute.Name) ? columnAttribute.Name : name };                     SetColumnName(column, property.Name);                     //分组                     if (columnAttribute is GroupColumnAttribute group) ListViewExtensions.SetGroup(column, group.Group);                     //宽度                     if (columnAttribute.Width > 0) column.Width = columnAttribute.Width;                     //转换器                     if (columnAttribute.Converter != null)                     {                         column.DisplayMemberBinding = new Binding(property.Name)                         {                             Converter = Activator.CreateInstance(columnAttribute.Converter) as IValueConverter,                             ConverterParameter = columnAttribute.ConverterParameter,                             StringFormat = columnAttribute.StringFormat                         };                     }                     else                     {                         //指定转换器                         var optionMappingAttribute = property.GetCustomAttributes().OfType<OptionMappingAttribute>().FirstOrDefault();                         if (optionMappingAttribute != null)                         {                             column.DisplayMemberBinding = new Binding(property.Name)                             {                                 Converter = optionMappingConverter,                                 ConverterParameter = optionMappingAttribute.Mapping                             };                         }                         else if (property.PropertyType.IsEnum)                         {                             column.DisplayMemberBinding = new Binding(property.Name)                             {                                 Converter = enumDescriptionConverter,                                 StringFormat = columnAttribute.StringFormat                             };                         }                         else                         {                             column.DisplayMemberBinding = new Binding(property.Name) { StringFormat = columnAttribute.StringFormat };                         }                     }                      SetColumnIndex(column, columnAttribute.Order);                     gridView.Columns.Add(column);                 }                  var cols = gridView.Columns.OrderBy(item => GetColumnIndex(item)).ToArray();                 gridView.Columns.Clear();                 foreach (var col in cols)                 {                     gridView.Columns.Add(col);                 }             }         }         #endregion          #region ColumnIndex         public static int GetColumnIndex(DependencyObject obj)         {             return (int)obj.GetValue(ColumnIndexProperty);         }          public static void SetColumnIndex(DependencyObject obj, int value)         {             obj.SetValue(ColumnIndexProperty, value);         }          public static readonly DependencyProperty ColumnIndexProperty =             DependencyProperty.RegisterAttached("ColumnIndex", typeof(int), typeof(ListViewExtensions), new PropertyMetadata(0));          #endregion          #region ColumnName         public static string GetColumnName(DependencyObject obj)         {             return (string)obj.GetValue(ColumnNameProperty);         }          public static void SetColumnName(DependencyObject obj, string value)         {             obj.SetValue(ColumnNameProperty, value);         }           public static readonly DependencyProperty ColumnNameProperty =             DependencyProperty.RegisterAttached("ColumnName", typeof(string), typeof(ListViewExtensions));         #endregion          #region Group         public static string GetGroup(DependencyObject obj)         {             return (string)obj.GetValue(GroupProperty);         }          public static void SetGroup(DependencyObject obj, string value)         {             obj.SetValue(GroupProperty, value);         }          public static readonly DependencyProperty GroupProperty =             DependencyProperty.RegisterAttached("Group", typeof(string), typeof(ListViewExtensions));          #endregion     }

二、示例代码

View

<ListView extensions:ListViewExtensions.AutoGenerateColumns="True" ItemsSource="{Binding Collection}"/>

Model

 public class Person : ValidationObjectBase     {         private string _name;         private DateTime _dateOfBirth = DateTime.Now;         private int _age;         private int _gender = 1;         private string _phoneNumber;         private string _email;         private string _address;         private string _idCardNumber;         private EducationInfo _education;         private MaritalStatus _maritalStatus;          /// <summary>         /// 姓名         /// </summary>         [Column(Name = "姓名", Order = 1)]         public string Name         {             get => _name;             set => this.SetProperty(ref _name, value);         }          /// <summary>         /// 出生日期         /// </summary>         [Column(Name = "出生日期", StringFormat = "{0:yyyy年MM月dd日}", Order = 2)]         public DateTime DateOfBirth         {             get => _dateOfBirth;             set => this.SetProperty(ref _dateOfBirth, value);         }          /// <summary>         /// 年龄         /// </summary>         [Column(Name = "年龄", Order = 3)]         public int Age         {             get => _age;             set => this.SetProperty(ref _age, value);         }          /// <summary>         /// // 性别         /// </summary>         [Column(Name = "性别", Order = 4)]         public int Gender         {             get => _gender;             set => this.SetProperty(ref _gender, value);         }          /// <summary>         /// 手机号码         /// </summary>         [Column(Name = "电话号码", Order = 5)]         public string PhoneNumber         {             get => _phoneNumber;             set => this.SetProperty(ref _phoneNumber, value);         }          /// <summary>         /// 电子邮箱         /// </summary>         [Column(Name = "电子邮箱", Order = 6)]         public string Email         {             get => _email;             set => this.SetProperty(ref _email, value);         }          /// <summary>         /// 地址信息         /// </summary>         [Column(Name = "地址", Order = 7)]         public string Address         {             get => _address;             set => this.SetProperty(ref _address, value);         }          /// <summary>         /// 身份证号码         /// </summary>         [Column(Name = "身份证号码", Order = 8)]         public string IdCardNumber         {             get => _idCardNumber;             set => this.SetProperty(ref _idCardNumber, value);         }          /// <summary>         /// 教育信息         /// </summary>         //[Column(Name = "教育信息", IsVisible = false, Order = 9)]         public EducationInfo Education         {             get => _education;             set => this.SetProperty(ref _education, value);         }          /// <summary>         /// 婚姻状况         /// </summary>         [Column(Name = "婚姻状况", Order = 10)]         public MaritalStatus MaritalStatus         {             get => _maritalStatus;             set => this.SetProperty(ref _maritalStatus, value);         }
}

ViewModel

public class FormDemoViewModel : BindableBase     {         public ObservableCollection<Person> Collection         {             get { return _collection; }             set { this.SetProperty(ref _collection, value); }         }     }

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

 三、答疑解惑

2.1 如何添加自定义列?

答:可以按常规方式添加自定义列,用ListViewExtensions.ColumnIndex来指定位的位置,以下为示例代码。

<ListView extensions:ListViewExtensions.AutoGenerateColumns="True" ItemsSource="{Binding Collection}">     <GridView>         <GridViewColumn extensions:ListViewExtensions.ColumnIndex="0">             <GridViewColumn.Header>                 <CheckBox Content="全选" />             </GridViewColumn.Header>             <GridViewColumn.CellTemplate>                 <DataTemplate>                     <CheckBox />                 </DataTemplate>             </GridViewColumn.CellTemplate>         </GridViewColumn>     </GridView> </ListView>

2.2 如何自动生成的列不满足需求,可不可以自己定义列?

答:可以,使用ListViewExtensions.ColumnName属性可以覆盖某一个列的自动生成的操作。

<ListView extensions:ListViewExtensions.AutoGenerateColumns="True" ItemsSource="{Binding Collection}">     <GridView>         <GridViewColumn                     extensions:ListViewExtensions.ColumnIndex="1"                     extensions:ListViewExtensions.ColumnName="Name">             <GridViewColumn.CellTemplate>                 <DataTemplate>                     <TextBlock Text="{Binding Name}" />                 </DataTemplate>             </GridViewColumn.CellTemplate>         </GridViewColumn>     </GridView> </ListView>

2.3 如何给列设置顺序?

答:在属性上给ColumnAttribute特性设置参数Order。

[Column(Name = "出生日期", Order = 2)] public DateTime DateOfBirth {       get => _dateOfBirth;       set => this.SetProperty(ref _dateOfBirth, value); }

2.4 如何设置列的宽度?

答:在属性上给ColumnAttribute特性设置参数Width。

[Column(Name = "出生日期", Width =100)] public DateTime DateOfBirth {       get => _dateOfBirth;       set => this.SetProperty(ref _dateOfBirth, value); }

2.5 如何将列设为不可见?

答:在属性上给ColumnAttribute特性设置参数IsVisible。

[Column(Name = "出生日期", IsVisible = false)] public DateTime DateOfBirth  {        get => _dateOfBirth;        set => this.SetProperty(ref _dateOfBirth, value); }

2.6 如何给绑定设置格式化字符串?

答:在属性上给ColumnAttribute特性设置参数StringFormat。

[Column(Name = "出生日期", StringFormat = "{0:yyyy年MM月dd日}")] public DateTime DateOfBirth {       get => _dateOfBirth;       set => this.SetProperty(ref _dateOfBirth, value); }

2.7 如何给绑定设置转换器及参数?

答:在属性上给ColumnAttribute特性设置Converter和ConverterParameter参数。

[Column(Name = "出生日期", Converter = typeof(TestConverter), ConverterParameter=1)] public DateTime DateOfBirth {       get => _dateOfBirth;       set => this.SetProperty(ref _dateOfBirth, value); }

 

技术交流群
一个可以让你有更多时间摸鱼的WPF控件(二)
 
联系方式
一个可以让你有更多时间摸鱼的WPF控件(二)