待上传商品筛选配置保存

This commit is contained in:
chfei committed 2026-09-17 18:02:37 +08:00
1 parent ab4f94e320
commit 1b9d2244c8
2 files changed
+444 -4

No files matched your search

+150
View File
@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TemuKJD.Extension;
public class DataContext<TSource> : BindingSource
{
public DataContext() { }
public DataContext(TSource dataSource) : base(dataSource, null) { }
// 强类型的 DataSource,避免调用方还要自己转型
public new TSource DataSource
{
get => (TSource)base.DataSource;
set => base.DataSource = value;
}
}
public static class BindingExtensions
{
/// <summary>
/// TSource 必须显式指定(因为无法从参数推断),TControl 自动从调用方控件推断
/// </summary>
public static Binding Bind<TSource, TControl>(
this TControl ctrl,
DataContext<TSource> dataSource,
Expression<Func<TControl, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
where TControl : Control
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyExpr, mode, format, parseHandler);
public static Binding Bind<TControl>(
this TControl ctrl,
BindingSource dataSource,
Expression<Func<TControl, object>> controlPropertyExpr,
string dataPropertyName,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null) where TControl : Control
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyName, mode, format, parseHandler);
// ---------- 共享的核心实现,不对外暴露 ----------
private static Binding BindCore<TSource>(
Control ctrl,
string controlPropertyName,
BindingSource bs,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode,
string format,
ConvertEventHandler parseHandler) => BindCore(ctrl, controlPropertyName, bs, dataPropertyExpr.GetPropertyName(), mode, format, parseHandler);
private static Binding BindCore(
Control ctrl,
string controlPropertyName,
BindingSource bs,
string dataPropertyName,
DataSourceUpdateMode mode,
string format,
ConvertEventHandler parseHandler)
{
var binding = new Binding(controlPropertyName, bs, dataPropertyName, true, mode);
if (!string.IsNullOrEmpty(format))
binding.Format += (s, e) => e.Value = string.Format($"{{0:{format}}}", e.Value);
if (parseHandler != null)
binding.Parse += parseHandler;
ctrl.DataBindings.Add(binding);
return binding;
}
// ---------- TextBox ----------
public static Binding Bind<TSource>(
this TextBox ctrl,
BindingSource bs,
Expression<Func<TextBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- CheckBox ----------
public static Binding Bind<TSource>(
this CheckBox ctrl,
BindingSource bs,
Expression<Func<CheckBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- DateTimePicker ----------
public static Binding Bind<TSource>(
this DateTimePicker ctrl,
BindingSource bs,
Expression<Func<DateTimePicker, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- ComboBox ----------
public static Binding Bind<TSource>(
this ComboBox ctrl,
BindingSource bs,
Expression<Func<ComboBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- NumericUpDown ----------
public static Binding Bind<TSource>(
this NumericUpDown ctrl,
BindingSource bs,
Expression<Func<NumericUpDown, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
public static string GetPropertyName<TSource, TProperty>(
this Expression<Func<TSource, TProperty>> propertyExpr)
{
if (propertyExpr.Body is MemberExpression member)
return member.Member.Name;
// 处理值类型属性被隐式转换为 object 的情况(如 decimal -> object)
if (propertyExpr.Body is UnaryExpression unary &&
unary.Operand is MemberExpression unaryMember)
return unaryMember.Member.Name;
throw new ArgumentException("表达式必须是形如 x => x.PropertyName 的属性访问", nameof(propertyExpr));
}
}