有条件地显示 WinForms UserControl 的属性?

Posted

技术标签:

【中文标题】有条件地显示 WinForms UserControl 的属性?【英文标题】:Conditional display of properties for a WinForms UserControl? 【发布时间】:2021-10-26 00:06:41 【问题描述】:

我有一个进行查找的 UserControl。它执行的查找类型取决于名为 LookupType 的属性。 UserControl 中有与每个 LookupType 相关的属性。例如,LookupType = Vendor 具有 Vendor_RemitToAddr 等属性,而 LookupType = ShipMeth 具有 ShipMeth_ShipMethID 等属性。

Intellisense 和“属性”窗口将它们全部显示出来,这是有道理的。但我希望能够让 UserControl 只公开与所选 LookupType 相关的属性。

有什么方法可以根据 LookupType 属性改变属性上的访问修饰符?

注意:这不是功能问题,而是用户体验问题。查找工作正常。但是在开发过程中看起来很乱,开发者-用户可能会错误地设置错误的属性。

【问题讨论】:

您可以尝试为您的 UserControl 实现 TypeConverter。覆盖GetProperties 方法并将RefreshProperties(RefreshProperties.All) 属性应用于LookupType 属性。那应该可以完成这项工作。 谢谢,斯蒂夫。我试图弄清楚这将如何工作。我不确定 GetProperties 方法是什么。那是反射中的GetProperties吗?我发现的 RefreshProperties 属性示例也有一个 AttributeProvider。我需要那个吗? Intellisense 将始终显示所有属性。如果您没有找到解决方案,我稍后会尝试为设计师制作样品。 谢谢!如果我设法弄清楚,我会在这里发布。 恐怕这是不可能的。为此,您需要更改用户控件上的modifiers 属性,这只能通过设计器完成。您可以做的是为您想要隐藏的那些属性分配一些值,并在设置器中编写一些代码,只要设置了此类型,它将拒绝任何其他值。不是您所要求的,但它可以阻止某人填写对此查找类型没有意义的属性 【参考方案1】:

这是一个 UserControl 的简化示例,只有 3 个属性:LookupTypeRemitToAddr(仅适用于 LookupType.Vendor)、ShipMethID(仅适用于 LookupType.ShipMeth)。一、LookupControl

public enum LookupType

    Vendor,
    ShipMeth


[TypeConverter(typeof(LookupControlConverter))]
public partial class LookupControl : UserControl

    private LookupType lookupType;

    public LookupControl()
    
        InitializeComponent();
    

    [RefreshProperties(RefreshProperties.All)]
    [Browsable(true)]
    public LookupType LookupType
    
        get => lookupType;
        set
        
            lookupType = value;
            // Clear out unwanted property values
            switch (value)
            
                case LookupType.Vendor:
                    ShipMethID = null;
                    break;
                case LookupType.ShipMeth:
                    RemitToAddr = null;
                    break;
            
        
    

    [Browsable(true)]
    public string RemitToAddr  get; set; 

    [Browsable(true)]
    public string ShipMethID  get; set; 

LookupControl 在LookupTypeproperty 设置器中包含一些逻辑,用于清除对当前 LookupType 没有意义的属性值。这可确保您的控件不能有不一致的属性值。 对于 Windows 窗体设计器中的 PropertyGrid,我实现了 TypeConverter

internal sealed class LookupControlConverter : TypeConverter

    private readonly PropertyDescriptorCollection allProps = TypeDescriptor.GetProperties(typeof(LookupControl), new[]  BrowsableAttribute.Yes );

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    
        if (context?.Instance is LookupControl)
            return true;
        return base.GetPropertiesSupported(context);
    

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    
        if (context.Instance is LookupControl control)
        
            var propList = allProps.Cast<PropertyDescriptor>().ToList();
            // Remove the unwanted property descriptors based on the current value of LookupType
            switch (control.LookupType)
            
                case LookupType.Vendor:
                    propList.Remove(allProps[nameof(LookupControl.ShipMethID)]);
                    break;
                case LookupType.ShipMeth:
                    propList.Remove(allProps[nameof(LookupControl.RemitToAddr)]);
                    break;
            
            return new PropertyDescriptorCollection(propList.ToArray(), true);
        
        return allProps;
    

注意:要使LookupControlConverter生效,您需要在用户控件上应用[TypeConverter(typeof(LookupControlConverter))]属性并在属性上应用[RefreshProperties(RefreshProperties.All)] LookupType。后者告诉设计者,如果属性发生变化,它应该重新查询所有属性(不仅仅是值)。然后 TypeConverter 只提供匹配的属性。

Visual Studio 中的 IntelliSense 没有解决方案,但如果你实现如上所示的属性,至少你可以保持属性值一致。

最后一点:Visual Studio 缓存了设计器中使用的控件。因此,如果您进行更改,您可能需要清理解决方案并重新启动 VS 以使更改生效。

【讨论】:

谢谢。这看起来像我需要的。

以上是关于有条件地显示 WinForms UserControl 的属性?的主要内容,如果未能解决你的问题,请参考以下文章

在 WinForms 桌面应用程序中使用 jQuery?

C# Winforms DataGridView 选定单元格正在清除单元格值

Winforms:没有绑定的快捷键文本

WinForms TreeView - 如何手动“突出显示”节点(就像点击它一样)

在winforms c#中自动调整项目/控件的大小显示错误

WinForms:寻找一种简单的方法来弹出“正在处理..”面板