You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms UserControl如何根据LookupType属性条件显示对应相关属性?

结论

不能动态修改属性的访问修饰符:访问修饰符是编译阶段就确定的元数据,运行时无法变更。但你可以通过.NET组件模型提供的能力,实现「仅在IntelliSense和属性窗口中暴露当前LookupType匹配属性」的需求,和你要的效果完全一致。

通用解决方案:实现ICustomTypeDescriptor接口

该接口是.NET为动态类型元数据场景提供的官方支持,设计器、IntelliSense都会优先读取该接口返回的属性列表,你只需要在对应方法中根据当前LookupType过滤属性即可,完整实现示例如下:

public enum LookupType
{
    None,
    Vendor,
    ShipMeth
}

public partial class LookupControl : UserControl, ICustomTypeDescriptor
{
    // 你原有的查询类型控制属性
    public LookupType LookupType { get; set; }

    // 各类型专属属性
    public string Vendor_RemitToAddr { get; set; }
    public int ShipMeth_ShipMethID { get; set; }

    // 核心方法:过滤要对外暴露的属性
    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        // 获取控件所有原生属性
        var allProps = TypeDescriptor.GetProperties(this, attributes, true);
        var filteredProps = new List<PropertyDescriptor>();

        foreach (PropertyDescriptor prop in allProps)
        {
            // 保留通用属性:LookupType本身、BackColor/Width等基础控件属性
            if (prop.Name == nameof(LookupType) || !prop.Name.Contains('_'))
            {
                filteredProps.Add(prop);
                continue;
            }

            // 专属属性仅保留和当前LookupType匹配的
            var propTypePrefix = prop.Name.Split('_')[0];
            if (LookupType.ToString() == propTypePrefix)
            {
                filteredProps.Add(prop);
            }
        }
        return new PropertyDescriptorCollection(filteredProps.ToArray());
    }

    // 剩余ICustomTypeDescriptor接口方法直接转发默认实现即可
    public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
    public string GetClassName() => TypeDescriptor.GetClassName(this, true);
    public string GetComponentName() => TypeDescriptor.GetComponentName(this, true);
    public TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true);
    public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
    public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
    public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
    public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
    public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true);
    public PropertyDescriptorCollection GetProperties() => GetProperties(null);
    public object GetPropertyOwner(PropertyDescriptor pd) => this;
}

补充优化

如果你需要避免开发者在代码中误用不匹配的属性,可以在专属属性的get/set逻辑中增加校验,示例如下:

private string _vendor_RemitToAddr;
public string Vendor_RemitToAddr
{
    get
    {
        if (LookupType != LookupType.Vendor)
            throw new InvalidOperationException($"仅当LookupType为{nameof(LookupType.Vendor)}时可访问该属性");
        return _vendor_RemitToAddr;
    }
    set
    {
        if (LookupType != LookupType.Vendor)
            throw new InvalidOperationException($"仅当LookupType为{nameof(LookupType.Vendor)}时可设置该属性");
        _vendor_RemitToAddr = value;
    }
}

该方案同时兼容WinForm、WPF的设计器,不需要额外适配。

内容的提问来源于stack exchange,提问作者Lisa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:27:01