visual studio - remove custom control from designer window - c#

I have a user control panel that has two buttons on it. Other user controls inherit from this control and set a property to true if the buttons should be visible. Everything runs how I want it to but what I'm looking for is a way to clear these buttons from the designer window for forms where this property is left at false.
looks like:
[DefaultValue(false)]
public bool ShowButtons{
set
{
mShowButtons = value;
UpdateButtons();
}
get
{
return mShowButtons;
}
}
This property shows in the properties window and the buttons are always shown in the designer window. Is there some way to have the designer evaluate this when the property is changed to get the buttons to clear from the inheriting form? I was unable find a designer attribute to do this.

Try adding a get:
bool mShowButtons;
[DefaultValue(false)]
public bool ShowButtons
{
get
{
return mShowButtons;
}
set
{
mShowButtons = value;
UpdateButtons();
}
}
Now when editing your derived class in the Designer, you should be able to see a ShowButtons property in properties window when the derived UserControl is selected. (It will be in the "Misc" section unless you add the appropriate attribute). If you set it there, it should have the appropriate affect in the Designer (Assuming the contents of the UpdateButtons() function work correctly)).
A property must be public and have bot get and set in order to display in the Properties editor window. Once it is, then setting the value in the properties window will "save" that setting for the designed control in the control's resources/implementation.
I use this functionality quite often to specialize derived UserControls, so I know it should work for you (although there may be other issues at play).

Related

How to get WinForms custom control's default value to be respected when first dropped on a form

I have a class library with a custom control in it:
using System.ComponentModel;
using System.Windows.Forms;
namespace ClassLibrary1
{
public sealed class CustomLabel : Label
{
[DefaultValue(false), Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override bool AutoSize
{
get => base.AutoSize;
set => base.AutoSize = value;
}
public CustomLabel()
{
AutoSize = false;
}
}
}
Notice that AutoSize is set to false in both the constructor and the designer attribute on the overridden method.
I have a winforms project where I want to use the control. I drag/drop it from the toolbox, but it doesn't have AutoSize set to false:
If I save and close the form and then re-open it, now it's set correctly:
How can I make it respect the property value when first dropped on the form?
The default values which you assign in constructor are respected in general. But for some cases the default values will be changed using designer, for example by the CreateComponentsCore method of ToolboxItem of the control.
The default value for AutoSize property for Label is false and you even don't need to override it or set it in constructor. But an AutoSizeToolboxItem has been assigned to Label which sets AutoSize to true when you drop an instance of Label on designer. To remove this behavior, it's enough to assign a new ToolboxItemto your control:
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
namespace ClassLibrary1
{
[ToolboxItem(typeof(ToolboxItem))]
public sealed class CustomLabel : Label
{
}
}
Note 1: Just for your information, the ToolboxItem has a CreateComponentsCore method which you can use it to to some initialization tasks when dropping control on design surface.
Note 2 I should also add, the CreateComponentCore method will just run when you drop the component from toolbox to design surface. It describes why after dropping it on form, it's auto-size, because it's set by CreateComponentCore after your constructor. But after you open the form again, this time, just your constructor will run and set the property to false.
The DefaultValueAttribute has no bearing on it: it mainly controls whether the property value should be serialized or not and whether the value should show in bold in the property editor window.
If you watch the designer code, initially it gets written out explicitly saving AutoSize as true. Apparently it saved the value because it doesnt match the value specified by the DefaultValue but it is saving the wrong value - apparently the base control hasnt gotten the update yet. Any change causes it to serialize the form again, this time with the correct value.
I dont know exactly why certain properties dont like being overridden and changed from the constructor, but there are a few that don't immediately take. AutoSize is one that gets handled thru SetStyle calls and/or thru some CommonProperties helper.
One way to set some of these is to implement ISupportInitialize to set the value after the control has been set from the designer properties. A simpler way is to override OnHandleCreated:
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
base.AutoSize = false;
}
Seems to work as desired.

WinForms - how to save the combobox selection in the app's settings?

I have a combobox embedded in a toolstrip - a ToolStripCombobox instance.
The list of items is the list of values of an enum.
I'd like to be able to load/save the selection (One of the Selected[Index|Item|Text|...] properties, from/to the app's Settings "mechanism".
Ideally, I'd like to be able to do that from the designer.
Normally, hooking a control's property to a certain setting is done (in the designer) from the control's properties, under (ApplicationSettings) - but none of the SelectedXXX properties shows up in there.
FWIW, in the particular case of toostrip-bound combo-boxes, the actual SelectedXXX properties are actually found a bit deeper, at toolStripComboInstance.ComboBox.SelectedXXX.
What I have done so far is configure the binding in code:
m_runTypeCombo //the toolstrip control
.ComboBox //the actual combobox
.DataBindings.Add(
new System.Windows.Forms.Binding(
"SelectedItem",
global::JavaPad.Properties.Settings.Default,
"RunType",
true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged
)
);
The above works, but I was hoping for something cleaner (i.e. designer-based). If the built-in ToolStripCombobox doesn't support this, is there a (simple) way to derive my own type from that, and expose the SelectedXXX properties in such a way that it works with the Application Settings infrastructure (and its support in the designer)?
If you are willing to wrap the TooltipComboBox in your own custom control, you can do it like this:
public class MyCombo : ToolStripComboBox
{
[SettingsBindable(true)]
public int SelectedIndex
{
get { return ComboBox.SelectedIndex; }
set { ComboBox.SelectedIndex = value; }
}
}
Note that I haven't tested this beyond confirming that I can add the control to the ToolStrip, and that I can select a property - You may need to add PropertyChanged Events to make it work fully.

Could not find a way to fill controls inside UserControl C#

I'm making such a tabbed "Product Version Control", using an UserControl which encloses fields, checkboxes, text areas, grids, and so on. At runtime, when I add a new tab (like we have on browsers), I instantiate a new UserControl (with all components inside). The issue is: I can get all internal component values and fill an object to persist, but not the other way. I can take all values from Object and set them to EditValue (or Text/Value properties) properties of internal components, but they are not showing up to the user.
Consider:
All my internal components have public set/get methods like shown below
public class TabVersion : UserControl
{
...
public DevExpress.XtraEditors.SpinEdit seRevision
{
get
{
return _seRevision;
}
set
{
_seRevision = value;
}
}
...
}
Inside TabVersion class, I have a "fill" method which receives an "Version" object and set all internal components "EditValue" properties like shown below:
public class TabVersion : UserControl
{
...
public void FillTab(Sheet sheet)
{
...
this.seRevision.EditValue = sheet.NumRevision;
...
}
...
}
At runtime, all EditValue component properties are filled but not showing to the user. Do I have to set "Enabled" or "Visible" properties for each component inside my usercontrol?
Any Ideas?
Thank you in advance.
Well... After googling everywhere with no goal, I wrote a "Fill" method that fills all DevExpress controls inside my user control, and called it inside the "Shown" event at the parent form. I think that's a bug from DevExpress, because all Windows default components works all right when I give them their respective values. That's it.

Visual Studio 2008 Form Designer messes up boolean properties values

I have a very annoying problem I'm trying to solve for couple of weeks. I have a WinForms C# project where I developed my custom control (ListView + ToolStrip with ToolStripButtons). This control is used in different forms inside solution - but in other projects. For different forms I need to make certain buttons visible or hidden, so I have added to my control corresponding properties like
public Boolean DeleteButtonVisible
{
get
{
return tsbDelete.Visible;
}
set
{
tsbDelete.Visible = value;
}
}
Some buttons are visible by default, some are hidden. In designer when editing a form with my control I'm able to change those properties, buttons on control become visible or hidden as they should. But every time I'm changing anything in my control source file in all forms those properties are reset to default values regardless of what I have set in designer and I have to restore those values manually. Well, I'm using a source control so this is not that hard, but performing "Undo" on a couple dozen of files every time I change a bit in another file is a damn disaster.
I have tried to use [DesignerSerializationVisibility] attribute to fix this issue. If I used it with value "Hidden" it didn't do any good at all - values were just not saved. "Content" made buttons randomly disappear even if by default they were visible. "Visible" lead to no effect, as this is default value...
I don't want to set every button visibility for every form in my code - this is just not the way it should be done.
Does anyone know something about this?
Yes, the Control.Visible property is special. The getter does not return the last assigned value, it only returns true when the control is actually visible. That can have side-effects, you've found one. In this case probably induced when the control switches out of design mode. To do this correctly, you must store the assigned state in a backing variable. Like this:
private bool tsbDeleteVisible;
public bool DeleteButtonVisible {
get { return tsbDeleteVisible; }
set { tsbDelete.Visible = tsbDeleteVisible = value; }
}
Be sure to initialize the default value of the backing variable to the default value of tsbDelete.Visible. Use the constructor to be sure.

How can you determine if Control.Visible is set via property or if the value is inherited

I need to find a way to determine if the Visible property of a control is set via a property change or if is inheriting it value from its parent. Using the Reflector, I find that the functions this.GetVisibleCore() and this.GetState() are both internal methods so I cannot call them.
The widgets themselves are created dynamically so I do not want to attach a method to the VisibleChanged event just after the creation of each widget so can try to monitor this property. If I have to, I guess I will but I am looking for something just a bit more elegant.
Edit
What I really want to know is when I hide the form and go to close it or build the form but keep it hidden, what Visible values are false because the form is hidden and what values are false because they were set to false. Again I do not want to have to attach a method to each VisibleChanged event of each widget. I just want to somehow read it off the Control object.
It's still not very clear, but I assume that the problem is that the Visible property getter returns the actual visibility state of the control. Which is not just the last assigned value to Visible, it also takes account of whether the parents of the control are visible. In other words, if you've got a button in a UserControl and the UserControl's Visible = false then the button's Visible will always be false as well.
You can override SetVisibleCore() to find out if the control intends to be visible:
public bool CouldBeVisible { get; set; }
protected override void SetVisibleCore(bool value) {
CouldBeVisible = value;
base.SetVisibleCore(value);
}

Categories

Resources