自学内容网 自学内容网

c# 动态lambda实现二级过滤(多种参数类型)

效果

调用方法

实体类(可以根据需求更换)

public class ToolStr50
{
    public bool isSelected { get; set; }

    public string toolStr1 { get; set; }
    public string toolStr2 { get; set; }
    public string toolStr3 { get; set; }
    public string toolStr4 { get; set; }
    public string toolStr5 { get; set; }
    public string toolStr6 { get; set; }
    public string toolStr7 { get; set; }
    public string toolStr8 { get; set; }
    public string toolStr9 { get; set; }
    public string toolStr10 { get; set; }

    public int toolInt1 { get; set; }
    public int toolInt2 { get; set; }
    public int toolInt3 { get; set; }
    public int toolInt4 { get; set; }
    public int toolInt5 { get; set; }
    public int toolInt6 { get; set; }
    public int toolInt7 { get; set; }
    public int toolInt8 { get; set; }
    public int toolInt9 { get; set; }
    public int toolInt10 { get; set; }
               
    public double toolDouble1 { get; set; }
    public double toolDouble2 { get; set; }
    public double toolDouble3 { get; set; }
    public double toolDouble4 { get; set; }
    public double toolDouble5 { get; set; }
    public double toolDouble6 { get; set; }
    public double toolDouble7 { get; set; }
    public double toolDouble8 { get; set; }
    public double toolDouble9 { get; set; }
    public double toolDouble10 { get; set; }

    public DateTime toolDate1 { get; set; }
    public DateTime toolDate2 { get; set; }
    public DateTime toolDate3 { get; set; }
    public DateTime toolDate4 { get; set; }
    public DateTime toolDate5 { get; set; }
    public DateTime toolDate6 { get; set; }
    public DateTime toolDate7 { get; set; }
    public DateTime toolDate8 { get; set; }
    public DateTime toolDate9 { get; set; }
    public DateTime toolDate10 { get; set; }
}

传入需要二级过滤的数据

 public void ShowSecondaryFiltration()
 {
     var columnMappings = new Dictionary<string, string>
         {
            { "采购日期", "toolStr26" },
             { "采购周期", "toolInt10" },
             { "采购回复交期", "toolStr31" },
             { "采购说明", "toolStr53" },
             { "生产订单号", "toolStr1" },
             { "来源单号", "toolStr2" },
             { "采购订单号", "toolStr3" },
             { "行号", "toolInt1" },
             { "料号", "toolStr4" },
             { "品名", "toolStr5" },
             { "规格描述", "toolStr6" },
             { "现存量", "toolInt2" },
             { "单位", "toolStr11" },
             { "采购数量(计量)", "toolInt3" },
             { "收货数量(计量)", "toolInt4" },
             { "已退货数(计量)", "toolInt5" },
             { "实际入库数(计量)", "toolInt6" },
             { "入库单号", "toolStr16" },
             { "已暂收数量(计量)", "toolInt7" },
             { "最后交货日期", "toolStr18" },
             { "逾期天数(负数未到期)", "toolInt8" },
             { "品质异常报告日期", "toolStr19" },
             { "品质问题描述", "toolStr20" },
             { "处理结论", "toolStr21" },
             { "未交数量(计量)", "toolInt9" },
             { "交货结案日期", "toolStr23" },
             { "请购日期", "toolStr24" },
             { "PMC交单日期", "toolStr25" },
             { "理论交期", "toolStr28" },
             { "要求交期", "toolStr29" },
             { "订单回传日期", "toolStr30" },
             { "色板_模板_图纸提供情况", "toolStr32" },
             { "异常反馈", "toolStr33" },
             { "预付款比例", "toolInt11" },
             { "预付款支付日期", "toolStr35" },
             { "尾款比例", "toolInt12" },
             { "尾款支付日期", "toolStr39" },
             { "采购员", "toolStr44" },
             { "请购制单人", "toolStr40" },
             { "供应商名称", "toolStr46" },
             { "请购单备注", "toolStr42" },
             { "采购单备注", "toolStr45" },
             { "可用量", "toolStr8" },
             { "含税单价", "toolDouble1" },
             { "含税金额", "toolDouble2" },
             { "采购到货日期", "toolStr37" },
             { "财务交单日期", "toolStr38" },
             { "请购人", "toolStr41" },
             { "采购制单人", "toolStr43" },
             { "采购订单结案状态", "toolStr48" },
             { "修改日期_请购", "toolStr50" },
             { "修改日期_采购", "toolStr51" },
             { "PMC要求交货日期", "toolStr52" }
         };
     var traceWindow = new TraceTableSecondaryFiltration(columnMappings, OdlIbo);

     traceWindow.QueryConditions = _queryConditions;

     if (traceWindow.ShowDialog() == true) // 检查对话框的结果
     {
         var filteredIbo = traceWindow.FilteredData;
         _queryConditions = traceWindow.QueryConditions;
         Ibo = filteredIbo;
         // 使用 filteredIbo 进行后续处理
     }
     if (_queryConditions.Count == 0)
     {
         SelectInfo();
     }
     //更新总条数和总金额
     InfoCount = "数据汇总:" + Ibo.Count.ToString() + "条";
     decimal total = Ibo.Sum(x => Convert.ToDecimal(x.toolStr10)); // 假设 TaxInclusiveSum 是 double 类型  
     total = decimal.Round(total, 4);//
     TaxinclusiveSum = "合计含税金额:" + total.ToString();

 }

窗体页面TraceTableSecondaryFiltration.xaml

<Window x:Class="GMWPF.Views.ModuleMenu.Purchase.PurchaseModle1.ChildWindow.TraceTableSecondaryFiltration"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:GMWPF.Views.ModuleMenu.Purchase.PurchaseModle1.ChildWindow"
        mc:Ignorable="d"
        Title="TraceTableSecondaryFiltration" Height="450" Width="800"
        WindowStartupLocation="CenterScreen">
    <Grid Margin="10" Name="myDynamicGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <!-- 让表格占用剩余空间 -->
        </Grid.RowDefinitions>
 
        <TextBlock Text="字段名称" Margin="49,34,655,0" VerticalAlignment="Top" Grid.Row="0"/>
        <ComboBox Name="FieldNameComboBox" 
          Margin="25,5,640,0" 
          VerticalAlignment="Top" 
          ItemsSource="{Binding FieldNames}" 
          SelectedItem="{Binding SelectedFieldName, Mode=TwoWay}" 
          SelectionChanged="FieldNameComboBox_SelectionChanged"
          Grid.Row="1"/>
        <TextBlock Text="条件" Margin="227,34,495,0" VerticalAlignment="Top" Grid.Row="0"/>
        <ComboBox Name="ConditionComboBox" 
                  Margin="184,5,471,0" 
                  VerticalAlignment="Top" 
                  ItemsSource="{Binding Conditions}" 
                  SelectedItem="{Binding SelectedCondition}" 
                  Grid.Row="1"/>
 
        <TextBlock Text="条件值" Margin="402,34,320,0" VerticalAlignment="Top" Grid.Row="0"/>
        <ComboBox Name="ValueComboBox" 
                  Margin="357,5,275,0" 
                  VerticalAlignment="Top" 
                  ItemsSource="{Binding ConditionValues}" 
                  SelectedItem="{Binding SelectedConditionValue}" 
                  Grid.Row="1"/>
 
        <TextBlock Text="关系" Margin="564,34,168,0" VerticalAlignment="Top" Grid.Row="0"/>
        <ComboBox Name="RelationComboBox" 
                  Margin="532,5,154,0" 
                  VerticalAlignment="Top" 
                  ItemsSource="{Binding RelationValues}" 
                  SelectedItem="{Binding SelectedRelationValue}" 
                  Grid.Row="1"/>
 
        <Button Content="添加" Command="{Binding AddQueryConditionCommand}" 
                Margin="637,5,0,0" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Top" 
                Height="27" 
                Grid.Row="1"/>
        <Button Content="查询" Command="{Binding QueryCommand}" 
                Margin="697,5,0,0" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Top" 
                Height="27" 
                Grid.Row="1"/>
        <DataGrid Name="ConditionDataGrid" 
          Grid.Row="2" 
          Margin="10,10,10,0" 
          BorderThickness="1"
          Height="300"
          AutoGenerateColumns="False" 
          ItemsSource="{Binding QueryConditions}">
            <DataGrid.Columns>
                <DataGridTextColumn Width="200" Header="字段名称" Binding="{Binding FieldName}">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                            <Setter Property="VerticalAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
 
                <DataGridTextColumn Width="100" Header="条件" Binding="{Binding Condition}">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                            <Setter Property="VerticalAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
 
                <DataGridTextColumn Width="200" Header="条件值" Binding="{Binding ConditionValue}">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                            <Setter Property="VerticalAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
 
                <DataGridTextColumn Width="100" Header="关系" Binding="{Binding RelationValue}">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center"/>
                            <Setter Property="VerticalAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
 
                <DataGridTemplateColumn Width="200" Header="操作">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="删除" Width="80" 
                                Command="{Binding DataContext.DeleteConditionCommand, 
                                                 RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                    CommandParameter="{Binding}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        </Style>
                    </DataGridTemplateColumn.HeaderStyle>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
 
    </Grid>
</Window>

窗体实现类TraceTableSecondaryFiltration.xaml.cs

这里在进行数据对比时对数据进行了类型转换,因为string类型的对比会出现

“4”>“20”的情况

using CommunityToolkit.Mvvm.Input;
using SQLSugarDB.Model.Public;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Expression = System.Linq.Expressions.Expression;
namespace GMWPF.Views.ModuleMenu.Purchase.PurchaseModle1.ChildWindow
{
    public partial class TraceTableSecondaryFiltration : Window
    {
        public List<ToolStr50> FilteredData { get; private set; }


        private Dictionary<string, string> _columnMappings;//所有的列和对应Toolstr属性的映射关系
        private List<ToolStr50> _Ibo;//所有的数据

        private List<string> _fieldNames = new List<string>(); // 字段名
        public List<string> FieldNames
        {
            get { return _fieldNames; }
            set
            {
                _fieldNames = value;
            }
        }

        private string _selectedFieldName;
        public string SelectedFieldName
        {
            get { return _selectedFieldName; }
            set
            {
                _selectedFieldName = value;

            }
        }


        private ObservableCollection<string> _conditions = new ObservableCollection<string>(); // 条件
        public ObservableCollection<string> Conditions
        {
            get { return _conditions; }
            set
            {
                _conditions = value;
            }
        }

        private string _selectedCondition;
        public string SelectedCondition
        {
            get { return _selectedCondition; }
            set
            {
                _selectedCondition = value;
            }
        }


        private ObservableCollection<string> _conditionValues = new ObservableCollection<string>(); // 条件值
        public ObservableCollection<string> ConditionValues
        {
            get { return _conditionValues; }
            set
            {
                _conditions = value;

            }
        }

        private string _selectedConditionValue;
        public string SelectedConditionValue
        {
            get { return _selectedConditionValue; }
            set
            {
                _selectedConditionValue = value;
            }
        }


        private ObservableCollection<string> _relationValues = new ObservableCollection<string>(); // 关系
        public ObservableCollection<string> RelationValues
        {
            get { return _relationValues; }
            set
            {
                _relationValues = value;
            }
        }

        private string _selectedRelationValue;
        public string SelectedRelationValue
        {
            get { return _selectedRelationValue; }
            set
            {
                _selectedRelationValue = value;
            }
        }


        private ObservableCollection<SecondQueryCondition> _queryConditions = new ObservableCollection<SecondQueryCondition>();


        public ObservableCollection<SecondQueryCondition> QueryConditions
        {
            get => _queryConditions;
            set
            {
                _queryConditions = value;
            }

        }

        public TraceTableSecondaryFiltration(Dictionary<string, string> columnMappings, List<ToolStr50> Ibo)
        {
            _columnMappings = columnMappings;
            _Ibo = Ibo;
            InitializeComponent();
            DataContext = this; // 设置数据上下文为当前窗口
            //将columnMappings所有的key拿出来放进List<string> _fieldNames中
            _fieldNames = new List<string>(_columnMappings.Keys);

            Conditions.Add("大于");
            Conditions.Add("大于等于");
            Conditions.Add("小于");
            Conditions.Add("小于等于");
            Conditions.Add("等于");
            Conditions.Add("不等于");

            RelationValues.Add("并且");
            RelationValues.Add("或者");
            //设定个默认值
            SelectedRelationValue = "并且";
        }
        [RelayCommand]
        public void AddQueryCondition()
        {

            // 检查是否有空值或空字符串
            if (string.IsNullOrEmpty(_selectedFieldName) ||
                string.IsNullOrEmpty(_selectedCondition) ||
                string.IsNullOrEmpty(_selectedConditionValue) ||
                string.IsNullOrEmpty(_selectedRelationValue))
            {
                return; // 如果有空值,直接返回
            }

            // 创建并添加 SecondQueryCondition 对象到 QueryConditions 列表
            QueryConditions.Add(new SecondQueryCondition(QueryConditions.Count + 1, _selectedFieldName, _selectedCondition, _selectedConditionValue, _selectedRelationValue));
        }
        private void FieldNameComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ConditionValues.Clear();
            _columnMappings.TryGetValue(_selectedFieldName, out string property);

            if (_Ibo == null)
            {
                return;
            }

            foreach (var item in _Ibo)
            {
                string propertyValue = item.GetType().GetProperty(property)?.GetValue(item)?.ToString();

                if (!string.IsNullOrEmpty(propertyValue) && !ConditionValues.Contains(propertyValue))
                {
                    ConditionValues.Add(propertyValue);
                }
            }
        }

        [RelayCommand]
        public void DeleteCondition(SecondQueryCondition secondQueryCondition)
        {
            QueryConditions.Remove(secondQueryCondition);
        }
        [RelayCommand]
        public void Query()
        {
            var parameter = Expression.Parameter(typeof(ToolStr50), "p");
            Expression finalExpression = null;

            foreach (var queryCondition in QueryConditions)
            {
                if (_columnMappings.TryGetValue(queryCondition.FieldName, out string property))
                {
                    var member = Expression.Property(parameter, property);
                    var conditionValue = Expression.Constant(queryCondition.ConditionValue, typeof(string));
                    Expression comparison;

                    // 尝试解析为 int, double, DateTime
                    if (int.TryParse(queryCondition.ConditionValue, out int intValue))
                    {
                        var intMember = Expression.Convert(member, typeof(int));
                        var intConditionValue = Expression.Constant(intValue, typeof(int));

                        comparison = GetIntegerComparison(queryCondition.Condition, intMember, intConditionValue);
                    }
                    else if (double.TryParse(queryCondition.ConditionValue, out double doubleValue))
                    {
                        var doubleMember = Expression.Convert(member, typeof(double));
                        var doubleConditionValue = Expression.Constant(doubleValue, typeof(double));

                        comparison = GetDoubleComparison(queryCondition.Condition, doubleMember, doubleConditionValue);
                    }
                    //如果日期类型无法对比直接注释掉,按照string类型对比
                    //else if (DateTime.TryParse(queryCondition.ConditionValue, out DateTime dateTimeValue))
                    //{
                    //    var dateTimeMember = Expression.Convert(member, typeof(DateTime));
                    //    var dateTimeConditionValue = Expression.Constant(dateTimeValue, typeof(DateTime));

                    //    comparison = GetDateTimeComparison(queryCondition.Condition, dateTimeMember, dateTimeConditionValue);
                    //}
                    else
                    {
                        // 如果无法转换,继续使用字符串比较
                        comparison = GetStringComparison(queryCondition.Condition, member, conditionValue);
                    }

                    // 组合条件
                    if (finalExpression == null)
                    {
                        finalExpression = comparison;
                    }
                    else
                    {
                        if (queryCondition.RelationValue.Equals("并且"))
                        {
                            finalExpression = Expression.AndAlso(finalExpression, comparison); // 使用 AndAlso 组合条件
                        }
                        if (queryCondition.RelationValue.Equals("或者"))
                        {
                            finalExpression = Expression.Or(finalExpression, comparison); // 使用 Or 组合条件
                        }
                    }
                }
            }

            // 生成最终的 Lambda 表达式
            if (finalExpression != null)
            {
                var lambda = Expression.Lambda<Func<ToolStr50, bool>>(finalExpression, parameter);
                FilteredData = _Ibo.Where(lambda.Compile()).ToList();
                this.DialogResult = true; // 可选: 设置窗口的结果
                this.Close(); // 关闭窗口
            }
            else //没有查询条件查全部
            {
                FilteredData = _Ibo;
                this.DialogResult = true; // 可选: 设置窗口的结果
                this.Close(); // 关闭窗口
            }
        }

        private Expression GetIntegerComparison(string condition, Expression member, Expression conditionValue)
        {
            return condition switch
            {
                "大于" => Expression.GreaterThan(member, conditionValue),
                "大于等于" => Expression.GreaterThanOrEqual(member, conditionValue),
                "小于" => Expression.LessThan(member, conditionValue),
                "小于等于" => Expression.LessThanOrEqual(member, conditionValue),
                "等于" => Expression.Equal(member, conditionValue),
                "不等于" => Expression.NotEqual(member, conditionValue),
                _ => throw new NotSupportedException($"不支持的条件: {condition}")
            };
        }

        private Expression GetDoubleComparison(string condition, Expression member, Expression conditionValue)
        {
            return condition switch
            {
                "大于" => Expression.GreaterThan(member, conditionValue),
                "大于等于" => Expression.GreaterThanOrEqual(member, conditionValue),
                "小于" => Expression.LessThan(member, conditionValue),
                "小于等于" => Expression.LessThanOrEqual(member, conditionValue),
                "等于" => Expression.Equal(member, conditionValue),
                "不等于" => Expression.NotEqual(member, conditionValue),
                _ => throw new NotSupportedException($"不支持的条件: {condition}")
            };
        }

        private Expression GetDateTimeComparison(string condition, Expression member, Expression conditionValue)
        {
            return condition switch
            {
                "大于" => Expression.GreaterThan(member, conditionValue),
                "大于等于" => Expression.GreaterThanOrEqual(member, conditionValue),
                "小于" => Expression.LessThan(member, conditionValue),
                "小于等于" => Expression.LessThanOrEqual(member, conditionValue),
                "等于" => Expression.Equal(member, conditionValue),
                "不等于" => Expression.NotEqual(member, conditionValue),
                _ => throw new NotSupportedException($"不支持的条件: {condition}")
            };
        }

        private Expression GetStringComparison(string condition, Expression member, Expression conditionValue)
        {
            // 比较两个字符串时,我们需要使用 string.Compare 方法
            var compareMethod = typeof(string).GetMethod("Compare", new[] { typeof(string), typeof(string) });

            return condition switch
            {
                // 等于
                "等于" => Expression.Equal(member, conditionValue),

                // 不等于
                "不等于" => Expression.NotEqual(member, conditionValue),

                // 大于
                "大于" => Expression.GreaterThan(
                    Expression.Call(null, compareMethod, member, conditionValue),
                    Expression.Constant(0)
                ),

                // 小于
                "小于" => Expression.LessThan(
                    Expression.Call(null, compareMethod, member, conditionValue),
                    Expression.Constant(0)
                ),

                // 大于等于
                "大于等于" => Expression.GreaterThanOrEqual(
                    Expression.Call(null, compareMethod, member, conditionValue),
                    Expression.Constant(0)
                ),

                // 小于等于
                "小于等于" => Expression.LessThanOrEqual(
                    Expression.Call(null, compareMethod, member, conditionValue),
                    Expression.Constant(0)
                ),

                _ => throw new NotSupportedException($"不支持的条件: {condition}")
            };
        }

    }
}

动态生成的lambda表达式:


原文地址:https://blog.csdn.net/wyh2943455568/article/details/143510683

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!