c# - 从 Control 派生但隐藏属性

标签 c# .net winforms

是的,我知道之前有人问过这个问题并回答过这个问题,但没有一个能完全解决几个问题。

引用资料

本质上,我想派生自 Control 但不公开某些属性。在我的例子中,我正在设计一个 Container,它将包含许多以编程方式排列的 Element。我希望(并且可能要求)Element 派生自 Control,以便获得所有绘图和事件,但也能够将 Element 对象添加到 ContainerChildren 集合(原因很明显)。

唯一的问题是,如果 Element 派生自 Control,那么它的 Location 属性就会暴露,用户可以很容易地破坏程序放置。自然地,我的直觉是保留所有随 Control 一起出现的好东西,并隐藏/禁用 Location

我知道以下内容:

  • 这违反了 SOLID Liskov 替换原则(按契约(Contract)设计)
  • 之前有人问过
  • 我可以将 Control 封装在我的 Element 中,并将所有调用转发给 Control 的调用
    • 这将是一项荒谬的工作量,而且没有任何实际 yield 。
    • 封装的 Element 仍然与 Control 类型不兼容,并且在许多情况下不能使用 Control 的派生形式会。

我觉得必须有一些更优雅的解决方案来解决这个(看似)反复出现的问题。提前致谢!

编辑

我认为实现此目的的唯一方法是:

public class Element : Control
{
    public new Point Location { get; private set; }
}

但是,我的问题是,我的容器类如何设置 Element 的位置?在 C++ 中,人们会使用友元类。我想如果我将这个控件保留在它自己的程序集中,我可以将 setter 标记为 internal

编辑

对于那些想做这件事的人,我的解决方案是:不做。相反,我制作了一个自定义对象并自己实现了所有的点击/拖动等操作。尝试使用控件太复杂了,同时排除了位置等功能。

最佳答案

您不能完全阻止 Control.Location 属性被坚定的程序员更新。使用 new 关键字将更改属性的可访问性,但它仅适用于 ElementElement 派生类引用。如果程序员将实例引用转换为 Control 的基类,则他们可以访问原始的 Location 属性,因此可以更新值。如果您不关心此解决方法,则只需继续并使用您在问题中显示的覆盖。

要真正防止除您的容器之外的任何人设置位置,您必须通过以下方式做更多的工作。对控件 LocationSize 的任何更改实际上都是通过调用虚拟 SetBoundsCore 方法来实现的。因此,您可以在 Element 类中重写此虚拟方法并忽略所有尝试的更改,除非设置了实例变量(如 AllowChange)。然后在您的容器中,您在更新大小/位置之前设置 AllowChange,然后再将其重置。现在更改大小的唯一方法是通过您的容器,或者如果程序员使用鲜为人知的更新属性。

关于c# - 从 Control 派生但隐藏属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6591849/

相关文章:

c# - 使用 Interlocked.CompareExchange 递增计数器直到一个值

c# - Guid 是值类型还是引用类型?

javascript - 在 Windows 窗体中单击 CefSharp 浏览器中的按钮

C# 如何将字符串转换为用于时间范围的时间格式?

c# - .net - Array.Sort 和 Array.BinarySearch 的问题 - 文化和全局化

c# - 如何知道在构建中使用哪个 cpu(x86 x64 或 AnyCpu)?

c# - IIS 7.5 在 ASP.Net 中获取一个 session 变量,但不是第二个

.net - paypal 与 .net 应用程序的集成可能是 Web 服务而不是网站

winforms - Windows 窗体中的用户控件 - 是否与 ASP.NET 用户控件类似?

sql - 无法识别指定的设置 'INSTALL'。错误代码 0x84B40003