首页 > 其他分享 >一个可以让你有更多时间摸鱼的WPF控件(二)

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

时间:2024-03-30 21:11:20浏览次数:17  
标签:控件 obj Name value columnAttribute 摸鱼 WPF public string

前言

  上文介绍了如何通过一个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); }
        }
    }

 三、答疑解惑

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);
}

 

标签:控件,obj,Name,value,columnAttribute,摸鱼,WPF,public,string
From: https://www.cnblogs.com/qushi2020/p/18106033

相关文章

  • WPF中继承ItemsControl子类控件数据模板获取选中属性
    需求场景列表类控件,如ListBox、ListView、DataGrid等。显示的行数据中,部分内容依靠选中时触发控制,例如选中行时行记录复选,部分列内容控制显隐。案例源码以ListView为例。Xaml部分<ListViewItemsSource="{BindingMyPropertys}"IsManipulationEnabled="False"><List......
  • 5.Android(RecyclerView控件总结)
    先说很重要很重要的问题就是在使用RecyclerView控件的时候根据课本我们需要导入recyclerview-v7库但是会出现一堆问题因为使用的是androidstudio是最新版需要手动更改很多东西而最新整合的Androidx解决了这个问题参考https://blog.csdn.net/weixin_43977534/article/de......
  • 【Qt】常用控件(输入类)
    目录一、LineEdit二、TextEdit三、ComBo四、DateTimeEdit五、Slider一、LineEditQLineEdit用来表示单行输入框,可以输入一段文本,但是不能换行。属性说明test输入框中的文本inputMask输入内容格式约束maxLength最大长度frame是否添加边框echoMode显示方式,normal,Pa......
  • WPF中使用PDF模板实现PDF导出和预览-来自GPT4
    在C#和WPF项目中实现加载不同的PDF模板、查看报告和导出PDF文件的功能,可以通过以下步骤完成:1.选择PDF库首先,选择一个合适的.NETPDF库。有许多库可以帮助你处理PDF文件,包括但不限于:iTextSharp:一个功能强大的和灵活的库,适用于创建和修改PDF文件。它是iText的一个.NET端口。......
  • WPF中实现动态表单-来自GPT4的回答
    实现C#和WPF项目中的动态表单功能,需要在后端设计灵活的数据结构来存储表单配置(例如字段名、字段类型等),同时前端需要能够解析这些配置并据此生成相应的控件。以下是一种可能的实现方法:1.数据库设计你的数据库需要至少包含两个表:一个用于存储表单字段的配置,另一个用于存储用户输......
  • 150. 如何使用 SAPGUI 中的树控件绘制树状数据结构
    大家在按照本文介绍的步骤进行学习之前,请务必先完成这两篇前置知识的学习:148.使用SAPGUI的Docking控件将屏幕划分成若干子区域149.如何在SAPGUI的ABAP报表里显示图片树形结构能够自然地表达层次化数据,如公司的组织架构、产品目录或项目任务的分解。在SA......
  • wpf write value to config file and read the persisted value
    <Windowx:Class="WpfApp26.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.......
  • WPF实现placeholder效果
     概述:WPF中通过`Style`实现TextBox水印文本,使用`WatermarkTextBox`类及`ControlTemplate`。这个示例通过`VisualStateManager`在文本框失去焦点且内容为空时显示水印文本。通过`Watermark`属性简化水印文本设置,提高可维护性。在WPF中,通过Style实现TextBox中的水印文本(水印、......
  • 一个可以让你有更多时间摸鱼的WPF控件(一)
    前言我们平时在开发软件的过程中,有这样一类比较常见的功能,它没什么技术含量,开发起来也没有什么成就感,但是你又不得不花大量的时间来处理它,它就是对数据的增删改查。当我们每增加一个需求就需要对应若干个页面来处理数据的添加、修改、删除、查询,每个页面因为数据字段的差异需要单......
  • 抢先看!界面控件DevExpress WPF 2024产品路线图预览(一)
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。本文将介绍2024年DevExpressWPF第一个主要更新(v2......