将父控件的属性传递给子控件
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
属性后,在这种情况下我们还应该实现ShouldSerializeXXXX
和ResetXXXX
方法,让设计者在序列化属性和右键单击 属性 并选择重置时如何重置值。
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();
}
}
我正在为特定应用程序开发一组自定义控件。为了外观目的,我想定义在一组控件上通用的属性,为了争论起见,让我们把它设为 CustomCtrl.AccentColor
我想为我的 Windows 表单定义相同的 属性,即 Form1.AccentColor
,当我更改它时,所有自定义控件的 AccentColor
都应该准确地更改就像当我更改表单的 ForeColor
时,所有标签和按钮等 ForeColor
都会随之更改。
完全有可能做到这一点,还是我必须满足于循环遍历所有自定义控件并逐一更改它的努力?
我认为您可以从控件 class 创建继承的 class 并在其中定义您的通用属性,然后从那个 class 继承您的自定义控件并使用父级 属性访问容器(如表单)并从中获取 属性 值
简答
正如您在评论中提到的那样,由于您可以为所有控件设置一个公共基础 class,作为一种选择,您可以创建一个基础 class,然后添加一些具有 ambient 属性(如 Font
)到基本控件 class。
详细解答
环境 属性 是控件上的 属性,如果未设置,则从父控件检索。
在我们的实现中,我们使用 FindForm
方法从父 Form
获取值。所以在实现中,当获取 属性 值时,我们检查该值是否等于默认值,如果来自的父级具有相同的 属性,我们 return 属性父窗体的值,否则我们 return 控件本身的 属性 值。
添加XXXX
属性后,在这种情况下我们还应该实现ShouldSerializeXXXX
和ResetXXXX
方法,让设计者在序列化属性和右键单击 属性 并选择重置时如何重置值。
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();
}
}