【问题标题】:How do I prevent access to the Items property in TCustomListView?如何防止访问 TCustomListView 中的 Items 属性?
【发布时间】:2014-08-21 23:50:15
【问题描述】:

我正在创建一个自定义组件,它派生自 TCustomListView

我不需要 Items 属性发布或在运行时由代码访问,因为我的自定义组件将处理项目的填充和访问。

我知道UnlistPublishedProperty 可以包含在您的组件的Register 过程中。因此,考虑到这一点,我尝试了:

UnlistPublishedProperty(TMyListView, 'Items');

据我了解,上述内容仅使该属性对对象检查器隐藏,因此代码MyListView1.Items 仍然存在。

如何使Items 属性(或我猜的任何属性)成为用户不可见、不可访问的属性,但我的组件仍可访问?

谢谢。

【问题讨论】:

    标签: delphi delphi-xe


    【解决方案1】:

    您不需要UnlistPublishedProperty 来安排不发布的属性。您可以简单地选择不发布该属性。

    要对代码和设计器隐藏它,你很不走运。你可以试试这个:

    ....
    private
      property Items;
    ....
    

    但它没有效果。来自documentation

    您可以通过重新声明属性来增加后代类中的属性的可见性,但不能降低其可见性。

    坦率地说,如果您希望您的控件不公开此属性,则不应从TCustomListView 开始。也许您需要封装而不是继承。

    【讨论】:

    • 同上。封装似乎是前进的方向。
    • 您能否详细说明encapsulate rather than inherit.?这到底是什么意思,例如,进一步深入链条并围绕TCustomListControl 构建我的组件?
    • 对不起,我理解了封装的概念,我只是说我不确定封装到底是什么,你的意思是如丹尼尔所说,本质上有一个内部列表视图?
    【解决方案2】:

    对于派生类,您只能增加属性的可见性,但不能减少。由于 Items 属性在 TCustomListView 中是公开的,因此无法对组件的用户隐藏它。

    【讨论】:

      【解决方案3】:

      据我所知这是不可能的。

      有两种接近的解决方法:

      1. 将 ListView 控件包装在您自己的控件中(例如,您创建一个内部包含列表控件的控件)。内部控件与客户区对齐,不使用任何框架/边框等。声明您希望在外部控件上公开/发布的属性。框架等属性应该应用到外部控件,其他属性应该转发到内部 ListView 控件
      2. 创建您自己的“ListView”控件(在内部转发到 WinAPI ListView 控件)。您可以复制 VCL“TCustomListView”控件的几乎所有内容,并在 Items 上使用 protected。 (如果您只是使用此控件,那应该没有问题。但是由于版权问题,您不应该使用它创建第 ​​3 部分库)。

      【讨论】:

        【解决方案4】:

        您可以在 Items getter 中引发异常告诉程序员他的错,并创建一个新的私有属性来存储您的列表内容...

        并覆盖所有方法以正确引用新的正确道具

        【讨论】:

        • 这对代码编写者来说是错误的,令人惊讶。
        【解决方案5】:

        好的,我想我可能已经解决了自己的问题。为此,我创建了一个名为 TMyListViewItems 的新类。

        从派生自 TCustomListView 的组件中,我在受保护的字段中有我的 Items 属性,这是我上面描述的类。

        类结构的 sn-p 看起来像这样:

          { TMyListViewItems }
          TMyListViewItems = class
          public
            constructor Create;
            destructor Destroy; override;
          end;
        
        { TMyListView }
          TMyListView = class(TCustomListView)
          private
            FItems: TMyListViewItems;
          protected
            property Items: TMyListViewItems read FItems;
          public
            constructor Create(AOwner: TComponent); override;
            destructor Destroy; override;
          published
            // publish default listview type properties if needed here..
            property Align;
            property BevelEdges;
            property BevelInner;
            property BevelKind;
            property BevelOuter;
            property BorderStyle;
            property Color;
            property Font;
            property HideSelection;
            property IconOptions;
            property MultiSelect;
            property ParentColor;
            property ParentFont;
            property TabStop;
          end;
        

        Items 属性在设计时或运行时不再可见或无法访问,这是我的主要目标。

        我发现的唯一缺点是任何人都可以将类型转换为 TListViewTCustomListView 并且原来的 Items 属性又回来了,但也许我不应该担心这个?

        TListView(MyListView1).Items.Add.Caption := 'test';
        

        【讨论】:

        • 你太努力了
        • @DavidHeffernan 我现在明白了,我试图拿一个现成的组件并切掉我不需要的部分,现在它似乎完全错误。更好地重新考虑我的整个方法以满足我的需求
        【解决方案6】:

        您可以使用 final 来防止后代类覆盖您的任何方法。如果您将该方法声明为严格私有,则 Code Insight 不会在任何后代类中显示该方法。不确定这是否也适用于属性

        Delphi 编译器也支持最终虚方法的概念。 当关键字 final 应用于虚方法时,没有后代 类可以覆盖该方法。使用 final 关键字是 重要的设计决策,可以帮助记录类是如何 打算使用。它还可以为编译器提供允许它的提示 优化它生成的代码。

        【讨论】:

        • 这与提出的问题无关,因为TCustomListView.Items 已经是公共财产。然后您不能将其更改为在后代中降低可见性并添加final 以隐藏公共Items
        猜你喜欢
        • 1970-01-01
        • 2011-10-26
        • 2013-09-25
        • 1970-01-01
        • 1970-01-01
        • 2017-09-16
        • 1970-01-01
        • 2016-08-27
        • 2015-12-04
        相关资源
        最近更新 更多