Can't set default value of property in custom control? - c#

The problem is I've already initialized all the initial values for my Properties in my Custom control constructor, for example, PropA = true. But when dragging-n-dropping the final Custom control onto a form, there are some values which are changed to different values (E.g: PropA = false).
I can understand why that happens, that's because of the auto-generated code which do very redundant works. I mean, only properties changed by us (programmers) in the properties window should be added with auto-generated code in the designer.cs files. Why does it have to add redundant code (and sometimes, unwanted code as in my case) to the designer.cs file. Here is the flow of code executing order which makes my default values go away:
public Form(){
//I replace the InitializeComponent() method by its content right in here
myCustomControl = new MyCustomControl(); <---- everything is already
//set up OK at here, no need auto-generated code for my custom properties.
SuspendLayout();
/////Initialize properties
//My custom properties go here, they are already set to default values in my
//custom control constructor (the line right at the very top above).
//And that means, all the auto-generated code below are preparing to erase
//all those default values unexpectedly.
myCustomControl.PropA = false; //While, PropA is already set to true
//in MyCustomControl() constructor and what I want is it should be true, not false
//but the designer doesn't understand me or I have to understand it????
//The same for other custom properties of mine
....
....
ResumeLayout(false);
PerformLayout();
}
I would like to know how to understand the designer or how to make it understand me???
Your help would be highly appreciated!
Thank you in advance!

Related

How to override Control.Enabled property in C# Winforms?

I have a custom control I am working on. I want to change its color when it is enabled or disabled. So I wrote a code inside OnEnabledChanged.
protected override void OnEnabledChanged(EventArgs e)
{
if (!Enabled)
{
temp1 = colorOn;
temp2 = colorOff;
colorOff = colorOn = Color.LightGray;
}
else
{
colorOn = temp1;
colorOff = temp2;
}
Invalidate();
base.OnEnabledChanged(e);
}
This code works fine in runtime but not design time. It wasn't raised when I changed the Enabled property in design time. So I want to override the Enabled property of the control. But it doesn't show up when typing it.
So how can I override it? If there is another way I want to use it.
That is entirely normal. One job of a control designer is to intercept the behavior of certain properties and methods that interfere with the use of the control in the design view. The Enabled property is one of them, if that would work at design-time as well then you could never select the control again. The designer can't let that happen of course, it always forces Enabled = true at design time and intercepts assignments to the property. As you found out. Overriding it can work either, it is not a virtual property, but wouldn't give you what you want anyway. The Visible property is another one that's intercepted like that, you can imagine how that goes wrong :)
You would have to create your own designer to do something about it. This in general tends to be a bazooka to kill a mosquito, especially in this case since you still can't do anything with Enabled. And worse, this behavior is implemented by the ControlDesigner class, the kind of class you need as a base class to get a designer going. I seriously doubt it is practical.
Doing nothing at all to fix this is entirely reasonable, given that none of the other controls in the toolbox change their appearance either when you change their Enabled property in the designer.

Avoid XAML Designer error with custom controls

Let's say that I have a custom control that inherits from another control.
I want to set some properties of this control, so I add something like this inside the constructor, for example:
public class MyControl : Canvas
{
public MyControl()
{
if (getSomeTestValueFromAppSettings())
{
this.Background = ColorConverter.MyStaticBrushProperty1;
}
else
{
this.Background = ColorConverter.MyStaticBrushProperty2;
}
}
}
Now, everything works fine inside the app, so no problems there.
The point is that if I add something like this inside my control constructor, I get an error with the XAML designer, and it tells me it can't create an instance of the control.
That's ok, since of course the constructor is trying to access the app local settings, and it can't do that inside the XAML Designer.
I'm currently using this as a workaround: I simply wrap all my conde inside the constructor inside a try/catch block, and if I got an exception (that only happens inside the XAML Designer) I simply ignore it.
This way the code stillworks fine on the phone, and it doesn't crash the XAMl Designer.
I don't think that this is a good solution though, a try/block inside a class constructor is not something I think could be considered a good programming practice.
I was hoping there was something like a "compiler directive" that tells the compiler when it's not actually running on a device/emulator, but just inside the XAML Designer, but I didn't find anything like that.
Do you have suggestions or other better ideas on how to solve that problem?
Thanks!
Sergio
There is actually a build-in method for situations like this.
Just use this code
if (DesignerProperties.GetIsInDesignMode(this))
{
// Design-mode specific functionality
}

Visual Studio wont let me remove the maximise/minimise button/icon etc

I have Form1.cs which I have set in properties to be borderless, without an icon, max/min buttons (and the changes are shown visually in Form1.cs), but when I debug/run, all of those controls stay the same as they previously were. The properties are then found in my code under private void InitializeComponent() as this.ShowIcon = false; etc.. Form1.Designer.cs is always empty though, have I messed up some settings somehow that overrides my form1.cs selections?
Have you tried setting the forms .MaximizeBox and .MinimizeBox to false ?
If so, can you please post the contents of that InitializeComponent method.
Winforms have properties like MinimizeBox, MaximizeBox and ShowIcon on the designer if you set then to False. Then you wont require any line of code in private void InitializeComponent()
Design view only show what is set in Form1.Design.cs, and not your custom code (except for some events and properties like resize...) Did you overwrite any design values in your code after you run InitializeComponents?
The easiest way is to cross-reference Form1.
If you're trying to remove the entire title bar you'll want to set the FormBorderStyle to None. If that doesn't work try and set a breakpoint after your form has loaded and check the values to make sure they are what you think they should be. This should not require any coding.

Interactive Design-Time User Control

I apologise if the title was confusing, it took me nearly 5 minutes to finally think of a title for this one...
Okay, you know how in Visual Studio Express when you add a TabControl to the Form, and you can click on the right-arrow on the top right of the TabControl and it will add a new TabPage, or remove one?
Well, I'm creating a User Control where I need people to be able to switch between Panels (my user control is made up of several Panels). I know this is possible as I've used a Ribbon Control in the past and you could add new buttons etc in the Designer View.
Can somebody please provide any suggestions/advice on how I might go about acheiving this?
Thank you
If I understand your question correctly, you're talking about smart tags.
The process is a little bit involved, so I'm not going to try to post a complete sample. Instead, I'll refer you to this tutorial on the subject. To make a long story short, you have to create a custom designer, and register one or more custom actions. You can use this to create a combo box listing the available panels and switch between them when the selected item is changed.
(Note - the term "smart tags" has two distinct meanings in Visual Studio - I'm specifically talking about the visual designer smart tags, not smart tags in the code editor).
When you make a control that is inherited from Control, you have to make use of a couple of properties such as IsDesignMode, you can then construct event handlers especially for within Design Mode:
if (IsDesignMode){
// Handle the interactivity in Design mode, such as changing a property on the
// Properties toolbox
}
Suppose the control has an event such as MouseClick, you can do this:
private void control_MouseClick(object sender, MouseEventArgs e){
if (IsDesignMode){
// Do something here depending on the Click event within the Designer
}else{
// This is at run-time...
}
}
Another I can think of is 'ShouldSerialize' followed by a publicly accessible property in order to persist the property to the designer-generated code, suppose for example a Control has a boolean property Foo
public bool Foo{
get{ return this._foo; }
set{ if (this._foo != value){
this._foo = value;
}
}
}
public bool ShouldSerializeFoo(){
return true; // The property will be persisted in the designer-generated code
// Check in Form.Designer.cs...
}
If ShouldSerializeFoo returned false, no property is persisted, its the opposite when true, it will be buried within the Form.Designer.cs code...
Hope this helps,
Best regards,
Tom.

How to create a derived ComboBox with pre-bound datasource that is designer friendly?

I'd like to create a derived control from System.Windows.Forms.ComboBox that is bound to a list of objects that I retrieve from the database. Idea is other developers can just drop this control on their form without having to worry about the datasource, binding, unless they want to.
I have tried to extend combobox and then set the DataSource, DisplayMember, and ValueMember in the constructor.
public class CustomComboBox : ComboBox
{
public CustomComboBox()
{
this.DataSource = MyDAL.GetItems(); // Returns List<MyItem>
this.DisplayMember = "Name";
this.ValueMember = "ItemID";
}
}
Works when I run, but throws a lot of errors in Visual Studio's once it's added to any form. The error I get is:
"Code generation for property 'Items' failed. Error was: 'Object reference not set to an instance of an object"
What's the correct way to accomplish this (C#, Winforms, .NET 2.0+)?
The problem is that the designer actually does some compilation and execution in a slightly different context than normally running the program does.
In the constructor, you can wrap your code in:
if (!DesignMode)
{
//Do this stuff
}
That will tell the designer to not run any of your initialization code while it is being designed.
DesignMode property doesn't work in a constructor. From googling for a while, found this LicenseManager thing.
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
// Do your database/IO/remote call
}
However LicenseManager only works in constructors. For eventhandlers use DesignMode.
Source: http://dotnetfacts.blogspot.com/2009/01/identifying-run-time-and-design-mode.html
Another reference: http://weblogs.asp.net/fmarguerie/archive/2005/03/23/395658.aspx
My usual comment here - DesignMode is not reliable in any situation other than if the control is placed directly on a design surface - i.e. if the control is placed on another control, DesignMode is not true even if you are in design mode. I have found NO reliable way to tell if you are in design mode - especially with inherited controls. Even variants using Site are not reliable if the control is inherited from a non-visual control (e.g. Common Dialog).
See http://keyofdflat.livejournal.com/5407.html (make sure to read the last comment).

Categories