将父控件的属性传递给子控件

Pass properties of parent control to children controls

我正在为特定应用程序开发一组自定义控件。为了外观目的,我想定义在一组控件上通用的属性,为了争论起见,让我们把它设为 CustomCtrl.AccentColor

我想为我的 Windows 表单定义相同的 属性,即 Form1.AccentColor,当我更改它时,所有自定义控件的 AccentColor 都应该准确地更改就像当我更改表单的 ForeColor 时,所有标签和按钮等 ForeColor 都会随之更改。

完全有可能做到这一点,还是我必须满足于循环遍历所有自定义控件并逐一更改它的努力?

我认为您可以从控件 class 创建继承的 class 并在其中定义您的通用属性,然后从那个 class 继承您的自定义控件并使用父级 属性访问容器(如表单)并从中获取 属性 值

简答

正如您在评论中提到的那样,由于您可以为所有控件设置一个公共基础 class,作为一种选择,您可以创建一个基础 class,然后添加一些具有 ambient 属性(如 Font)到基本控件 class。


详细解答

环境 属性 是控件上的 属性,如果未设置,则从父控件检索。

在我们的实现中,我们使用 FindForm 方法从父 Form 获取值。所以在实现中,当获取 属性 值时,我们检查该值是否等于默认值,如果来自的父级具有相同的 属性,我们 return 属性父窗体的值,否则我们 return 控件本身的 属性 值。

添加XXXX属性后,在这种情况下我们还应该实现ShouldSerializeXXXXResetXXXX方法,让设计者在序列化属性和右键单击 属性 并选择重置时如何重置值。

MyBaseControl

using System.Drawing;
using System.Windows.Forms;
public class MyBaseControl : Control
{
    public MyBaseControl()
    {
        accentColor = Color.Empty;
    }
    private Color accentColor;
    public Color AccentColor
    {
        get
        {
            if (accentColor == Color.Empty && ParentFormHasAccentColor())
                return GetParentFormAccentColor();
            return accentColor;
        }
        set
        {
            if (accentColor != value)
                accentColor = value;
        }
    }
    private bool ParentFormHasAccentColor()
    {
        return this.FindForm() != null &&
               this.FindForm().GetType().GetProperty("AccentColor") != null;
    }
    private Color GetParentFormAccentColor()
    {
        if (ParentFormHasAccentColor())
            return (Color)this.FindForm().GetType()
                               .GetProperty("AccentColor").GetValue(this.FindForm());
        else
            return Color.Red;
    }
    private bool ShouldSerializeAccentColor()
    {
        return this.AccentColor != GetParentFormAccentColor();
    }
    private void ResetAccentColor()
    {
        this.AccentColor = GetParentFormAccentColor();
    }
}

MyBaseForm

public class BaseForm : Form
{
    [DefaultValue("Red")]
    public Color AccentColor { get; set; }
    public BaseForm()
    {
        this.AccentColor = Color.Red;
    }
}

Form1

public partial class Form1 : BaseForm
{
    public Form1()
    {
        InitializeComponent();
    }
}