I apologize if the terminology is incorrect - not sure whether to call it an inherited control, custom control, or user control. Anyway please keep in mind this is a compact framework 3.5/smart device development question. I have a control that I have made that inherits from a button. Basically it draws a gradient and rounds the corners. I have 6 custom properties that I have added to this control. I noticed that when I set the value of one of these properties in the property window in the designer, I can never "reset" the value (ie right mouse click -> reset). The issue is that one of those properties is an image and now the only way to clear that image is to delete the button from the form and recreate it. I tried setting a default value in DesignTimeAttributes.xmta file for all the properties but that didn't seem to help. "Reset" is still disabled. Any help is appreciated. Code from the Image property of the class follows:
Private _Image As Bitmap = Nothing
Public Property Image() As Bitmap
Get
Return _Image
End Get
Set(ByVal value As Bitmap)
_Image = value
Invalidate()
End Set
End Property
Try this:
public void ResetImage()
{
if (Image != null)
{
Image.Dispose();
Image = null;
}
}
You can always create Reset method for any Property:
public void Reset[PropertyName]()
{
// Reset your property
}
Note: The designer won't call the Reset method if you set the DefaultValue in Xmta.
Related
I made a class derived from Button Class. It has two new properties: ImageNormal and ImageOver. I really want to hide the default Image property in Debug time.
Excuse me for my English, I know, I should improve it.
I solved it:
<System.ComponentModel.Browsable(False)>
Public Shadows Property Image As Image
Get
Return MyBase.Image
End Get
Set(value As Image)
MyBase.Image = value
End Set
End Property
I know that I can add a design-time Designer description to a custom control's property by doing this:
<Category("Data"), Description("This describes this awesome property")>
Public Property Foo As Boolean
...
End Property
What I want to do is the exact same thing, but to properties that my extender provider component is providing other controls on my form with, so that when I click on the property's value field, for example, I would see the description I wrote for it. Searched a lot for an answer but had no success so far. Would I have to add something to my getter and setter methods for the property?
Thank you.
Would I have to add something to my getter and setter methods for the property?
Yes. Add the DescriptionAttribute to the Get[PropertyName] method. The same goes for any other Attributes (they dont seem to work on the Set... counterpart).
<Category("ListContolExtender"), DisplayName("DisplayMode"),
Description("My very clever description")>
Public Function GetDisplayMode(ctl As Control) As ItemDisplays
If extData.ContainsKey(ctl) Then
Return extData(ctl).DispMode
Else
Return ItemDisplays.Enabled
End If
End Function
Public Sub SetDisplayMode(ctl As Control, v As ItemDisplays)
If extData.ContainsKey(ctl) Then
extData(ctl).DispMode = v
Else
Dim e As New ExtenderData
e.DispMode = v
extData.Add(ctl, e)
End If
End Sub
The DisplayNameattribute hides all the DisplayMode on ListBoxExtender verbiage
If I override a member (e.g AutoSize in the Button Class), then the intellisense no longer appears in the editor, forcing me to re-decorate the property.
Is there an option somewhere that I need to check?
ETA: Here's a code sample:
Public Class MyButton
Inherits Button
Public Overrides Property AutoSize() As Boolean
Get
Return MyBase.AutoSize
End Get
Set(ByVal value As Boolean)
MyBase.AutoSize = value
End Set
End Property
End Class
If I then type:
Dim b as New MyButton
b.AutoSize ...
The intellisense explaining the AutoSize property doesn't appear.
Whether a property is visible in IntelliSense is controlled by the [EditorBrowsable] attribute. VB.NET is a bit special because it hides EditorBrowsableState.Advanced by default.
None of this would apply to an override to Button.AutoSize, it is always visible. Maybe you can give a better example, a code snippet is always good.
I'm writing a custom DataGridView object for a large project to hand out to a bunch of developers to make our app sections look consistent.
I want to set defaults for many of the properties of the DataGridView, and I can set many of them like this:
<System.ComponentModel.Browsable(True), System.ComponentModel.DefaultValue(DataGridViewAutoSizeColumnsMode.Fill)>_
Public Overloads Property AutoSizeColumnsMode() As DataGridViewAutoSizeColumnMode
Get
Return MyBase.AutoSizeColumnsMode
End Get
Set(ByVal value As DataGridViewAutoSizeColumnMode)
MyBase.AutoSizeColumnsMode = value
End Set
End Property
These properties overload with their defaults just fine. Its when I started trying to make default Cell styles that I ran into the issue. Since the DataGridViewCellStyle is a class, I cannot make a constant out of it. I've tried changing all of the settings to what I want them to be in the class constructor, and that works great, except that changes made in the designer properties just get set back as soon as the app runs. So putting the changes in the constructor won't do.
Is there anywhere else I can put code that only runs when the control is first dropped on the designer? or any other way of setting a default?
I ran into this problem too. My solution works around the requirement for the DefaultValue argument to be a compile-time constant. I thought, wouldn't it be sufficient to set the value in the class constructor (defined by the static constructor in C#, and the shared constructor in VB) instead?
This seems to be an good work-around in my case, though there are probably instances where it might break since it's not actually present in the meta-data until the class constructor is called upon loading the class, but for a Designer attribute that should be acceptable. Because DefaultValueAttribute.SetValue is protected, I had to define a derived class that makes it public.
This works fine in the designer, it recognizes when the value is the same as the default and omits it from the generated code when possible, and only generates the differences from the default.
Here's the code in C#, this should work in VB too but I'm not overly familiar with its syntax so I'll have to leave that up to you.
public partial class HighlightGrid : DataGridView
{
// Class constructor
static MethodGrid()
{
// Get HighlightStyle attribute handle
DefaultValueSettableAttribute attr =
TypeDescriptor.GetProperties(typeof(HighlightGrid))["HighlightStyle"]
.Attributes[typeof(DefaultValueSettableAttribute)]
as DefaultValueSettableAttribute;
// Set default highlight style
DataGridViewCellStyle style = new DataGridViewCellStyle();
style.BackColor = Color.Chartreuse;
attr.SetValue(style);
}
[DefaultValueSettable, Description("Cell style of highlighted cells")]
public DataGridViewCellStyle HighlightStyle
{
get { return this.highlightStyle; }
set { this.highlightStyle = value; }
}
// ...
}
// Normally the value of DefaultValueAttribute can't be changed and has
// to be a compile-time constant. This derived class allows setting the
// value in the class constructor for example.
public class DefaultValueSettableAttribute : DefaultValueAttribute
{
public DefaultValueSettableAttribute() : base(new object()) { }
public new void SetValue(Object value) { base.SetValue(value); }
}
Actually, I thought about it a while longer and came across a simpler solution for my issue. This does not work for all cases because it relies on the fact that the person using the custom component will likely never want to revert an entire CellStyle back to windows defaults. I ended up comparing a new CellStyle to the current one in the constructor, and only setting the style if they matched. This way it won't overwrite changes, but it will set it up the first time.
Public Class CustomDataGridView
Inherits System.Windows.Forms.DataGridView
Private RowStyle As New DataGridViewCellStyle
Public Sub New()
RowStyle.BackColor = Color.FromArgb(223, 220, 200)
RowStyle.Font = New Font("Arial", 12.75, FontStyle.Bold, GraphicsUnit.Point)
RowStyle.ForeColor = Color.Black
RowStyle.SelectionBackColor = Color.FromArgb(94, 136, 161)
If MyBase.RowsDefaultCellStyle.ToString = (New DataGridViewCellStyle).ToString Then
MyBase.RowsDefaultCellStyle = RowStyle
End If
End Sub
End Class
Just goes to show, Just because you have a golden hammer, doesn't mean that every problem is a nail.
Solution
I did some googling and found this forum post, and here is what I needed to do:
Imports System.ComponentModel
<EditorBrowsable(EditorBrowsableState.Always), Browsable(True), Bindable(True), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Overrides Property Text() As String
Get
Return ControlText.Text
End Get
Set(ByVal value As String)
ControlText.Text = value
End Set
End Property
I should state that I am really new to creating custom controls, so I do not know all of the ins-and-outs of the whole process.
I am creating a custom control that functions similarly to a checkbox, but uses two images as checked/unchecked. I am trying to add a Text property, but it gives me this warning:
Property Text() As String
Get
Return ControlText.Text
End Get
Set(ByVal value As String)
ControlText.Text = value
End Set
End Property
"property 'Text' shadows an overridable method in the base class 'UserControl'. To override the base method, this method must be declared 'Overrides'."
Ok, so that is no problem. I change my declaration to Overrides Property Text() As String, but when I go to test it out 'text' is not listed under properties. Is there additional steps I need take to get my result?
More details
My control consists of 2 (or 3, depending on how you look at it):
PictureBox - Displays a checked/unchecked image
Label - The Text that is being displayed on the control
PictureCheckBox - This is the actual control's name
The PictureBox is docked to the left of the PictureCheckBox, and the Label is docked on the right side:
EDIT Scratched the bit about Text being non-virtual. It is in fact virtual / overridable.
But I'm curious, why do you want to do this. In your specific example you're just calling into the base property so it doesn't appear to do anything.
Where are you expecting this value to be shown and how are you setting it?
Text is a non-virtual / overridable method on Control. There is no way for you to override the property. If you want to re-define the property you can use the Shadows keyword.
You should make sure it's a public property
Public Overridable Property Text() As String
Get
Return ControlText.Text
End Get
Set(ByVal value As String)
ControlText.Text = value
End Set End Property
This might be a stupid question, but some of them still needs to be asked just to make sure:
Have you compiled since you made the changes? Using hotkeys in Visual Studio, press [Ctrl]+[Shift]+[b] to compile the entire solution.