First: the wording of the question may be inaccurate, sorry for that. The actual question is below all code snippets.
Second: the code is in C#, but I usually write code in VB.NET.
I have a class LabelData
which contains data for the visual appearence of a user drawn label. Short example:
public class LabelData
{
public Color BackColor1 { get; set; }
public Color BackColor2 { get; set; }
public Color TextColor { get; set; }
public int TextAngle { get; set; }
public string Text { get; set; }
}
My UserControl
draws a lot of text (lets call them small labels) using LabelData
. It looks like this (simplified):
public class UserControl1
{
public LabelData Title { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
// draw title here
LabelData currentLabel;
for (int i = 0; i <= 9; i++)
{
currentLabel = new LabelData();
currentLabel.BackColor1 = Color.Green;
currentLabel.BackColor2 = Color.YellowGreen;
currentLabel.TextAngle = 0;
currentLabel.Text = "Element" + i.ToString();
// draw text here
}
}
}
All data for the small labels are defined within OnPaint
. I don't want this. I thought of a Template for the smaller labels like the DataGridViewRowTemplate
. This also allows me to implement ICloneable
for LabelData
.
This would change to:
public class UserControl1
{
public LabelData Title { get; set; }
public LabelData LabelTemplate { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
LabelData currentLabel;
for (int i = 0; i <= 9; i++)
{
currentLabel = LabelTemplate.Clone();
currentLabel.Text = "Element" + i.ToString();
}
}
}
Now the question: How can I remove the Text
-Property for the LabelTemplate
property (but not for the Title
property) in a PropertyGrid
since this property changes in OnPaint
anyways?
PS: I tried to create a custom designer and overwrite PreFilterProperties
to remove the Text
property, but I couldn't add a DesignerAttribute
to the LabelTemplate
property.
Since you probably will need an ExpandableObjectConverter to present properties assigned from your LabelData
Class objects, you could create a Custom TypeConverter based on ExpandableObjectConverter
and remove Properties from the base Class Object, when you want to present this object differently in specific circumstances.
Here, as example, while both Title
and Template
properties are shown as an expandable object in the PropertyGrid (so you can edit each property value with its specific type editor), the Template
property has a slightly different Type Converter, where the GetProperties()
method is overridden to remove the Text
property from the underlying Class object, so it won't be shown in the PropertyGrid:
The Template expandable object property doesn't show the Text property as its fellow Title property
C# version:
public class UserControl1
{
public UserControl1() {
Template = new LabelData() { ... };
Title = new LabelData() { ... };
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public LabelData Title { get; set; }
[TypeConverter(typeof(CustomExpandableConverter))]
public LabelData Template { get; set; }
// [...]
}
public class CustomExpandableConverter : ExpandableObjectConverter
{
public CustomExpandableConverter() { }
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
var props = base.GetProperties(context, value, attributes)
.OfType<PropertyDescriptor>().Where(pd => pd.Name != "Text").ToArray();
return new PropertyDescriptorCollection(props);
}
}
VB.Net version:
Public Class UserControl1
Public Sub New()
Template = New LabelData()
Title = New LabelData()
End Sub
<TypeConverter(GetType(ExpandableObjectConverter))>
Public Property Title As LabelData
<TypeConverter(GetType(CustomExpandableConverter))>
Public Property Template As LabelData
'[...]
End Class
Public Class CustomExpandableConverter
Inherits ExpandableObjectConverter
Public Sub New()
End Sub
Public Overrides Function GetProperties(context As ITypeDescriptorContext, value As Object, attributes() As Attribute) As PropertyDescriptorCollection
Dim props = MyBase.GetProperties(context, value, attributes).
OfType(Of PropertyDescriptor)().
Where(Function(pd) Not pd.Name.Equals("Text")).ToArray()
Return New PropertyDescriptorCollection(props)
End Function
End Class