|
前言
上文介绍了如何通过一个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- [/code][b]Model[/b]
- [code] 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);
- }<br>}
复制代码 ViewModel- public class FormDemoViewModel : BindableBase
- {
- public ObservableCollection<Person> Collection
- {
- get { return _collection; }
- set { this.SetProperty(ref _collection, value); }
- }
- }
复制代码
三、答疑解惑
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);
- }
复制代码
来源:https://www.cnblogs.com/qushi2020/p/18106033
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|