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