Refreshing a user control in design time depending on a property - c#

I have a custom control with a bool property. In the designer, I drag the user control to a form and I change this property to "false", which is supposed to hide a child control.
It is indeed hiding it in runtime, but not in design time. How could I "refresh" my user control in design time to reflect the changes to this property?

I don't know why you want to do this. The Control will only be hidden at runtime and this is how it was meant to be. Maybe you can create something to hide it at Design-Time or add another control over it to hide it.
How could I "refresh" my user control in design time to reflect the changes to this property?
You can't. Changes apply automatically the only reason why you still see it is because that's how it should be.

This worked as is using Visual Studio 2012:
public class TestControl : Control {
Button button;
public TestControl() {
button = new Button() { Text = "Click" };
this.Controls.Add(button);
}
public bool ButtonVisible {
get { return button.Visible; }
set {
button.Visible = value;
}
}
}

I'm afraid I didn't ask my question correctly - I was inheriting from a rather complex third-party control and I wanted to see a change in design time.
I ended up overriding OnCreateControl. I appreciate your help nevertheless.

Related

C# Using a form to load other user controls and have access to a base control or property

Currently I have a C# program with a windows form and then a user control template put onto the form. The user control template is really just used as a placeholder. I have a series of other controls which inherit from this user control template.
Each of those controls have navigation buttons like 'Continue' and 'Back' on them and each control knows which control needs to be loaded next. However what I need to figure out is an easier way to have variables that are global to these controls.
The only workaround I have is that I pass the form to each control when they are loaded and use variables inside of the form to read and write to. What would be the proper way to have each of these user control screens be built off of a base control which contained objects all of the controls could get to?
Sorry for the rambling nature of the post but I've been thinking about this problem all morning.
Here is some of the code:
Most of what I have written was based on hiding and showing the user controls so that content in the controls wouldn't be lost during navigation. I won't be needing to do that as eventually it will be loading the fields of data from a database.
Code for initially loading control from form click:
conTemplate1.Controls.Clear();
conInbound Inbound = new conInbound(this);
Inbound.Dock = DockStyle.Fill;
Inbound.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
conTemplate1.Controls.Add(Inbound);
Code for Continue button inside of one of the controls:
if ((Parent.Controls.Count - 1) <= Parent.Controls.IndexOf(this))
{
UserControl nextControl = new conPartialClear();
nextControl.Dock = DockStyle.Fill;
Parent.Controls.Add(nextControl);
this.Hide();
Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
}
else
{
this.Hide();
Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
}
The best-practice for communicating from a control to a parent is to use events, and for communicating from a parent to a control is to call methods.
However, if you don't want to or can't follow this practice, here's what I would recommend.
Each UserControl has a ParentForm property that returns the Form that contains the control. If you know that the UserControl will always be attached to MyParentForm, you just cast the ParentForm and then you can access all public controls, methods, etc.
Here's what I mean:
public class conTemplate
{
public MyParentForm MyParentForm
{
get
{
return (MyParentForm)this.ParentForm;
}
}
}
This way, you can easily access any public members of MyParentForm. Your conInbound class could have code such as this.MyParentForm.GlobalSettings.etc..., and could even have access to any public controls.
I'm not totally sure I understand your problem. It sounds like you want the user control to "do something" with it's parent form. If that's the case, you may want to consider adding events to the UC and then handle them on the form itself.
Basically, for your UC's "continue", you'll have an event that's fired when it's pressed. You'll want to handle that in your form. I'm not real sure about the syntax from memory, or I'd work something out for you code-wise. But I think that's the route you'll want to take. Think of your UC like any other windows form control. If you add a button to your form, you assign it it's event method. Do the same with the UC.
I found this and thought it may be helpful. Scroll down to where it talks about UC's and events.
http://www.akadia.com/services/dotnet_user_controls.html
Hope this helps.
EDIT after new info from OP.
You could declare a global variable inside the UC of type yourForm and then set that variable to the ParentForm at run-time, if I'm understanding you correctly.
So, inside your UC Class, you could do:
private parentFormInstance;
then inside the constructor of the UC, you could set it as such:
parentFormInstance = this.ParentForm; (or whatever the property name is).
This allows you at design-time to use:
parentFormInstance.DoSomething();
without the compiler yelling at you.
Just basic advice, but if you can go back and make it easier on yourself, even if it takes some additional time re-working things, it'd be worth it. It may save you time in the long run.

Winform Custom Control: Why Setter not called when used from Constructor?

I have an initial value property like this:
[Category("Main")]
[Description("Intial Value")]
[DefaultValue(10)]
public int InitialValue
{
get { return m_initialValue; }
set {
m_initialValue = value;
this.TrackBar.Value = this.m_initialValue;
}
}
So in my constructor I do this for example:
this.InitialValue = 10;
To my surprise when dragging the custom control on a form the setter is not called so that my trackbar value is not synchronized.
Why ?
Only when I change the property in dialog box the setter is called.
I decided to take your advice as suggested in one of the comments:
You can try by yourself will take 2 minutes.
So I did (it took about 3 minutes), and I was unable to reproduce the behavior that you described.
Here are the exact steps that I followed:
Created a new Windows Forms Application.
Added a new User Control to my project.
Opened the new User Control in design view and added a TrackBar control (leaving the TrackBar control's properties all set to their defaults).
Added the following code to the User Control class (exactly the same as you posted above, with the addition of a private field m_initialValue that you omitted from the original example):
public class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.InitialValue = 10;
}
[Category("Main")]
[Description("Intial Value")]
[DefaultValue(10)]
public int InitialValue
{
get { return m_initialValue; }
set
{
m_initialValue = value;
this.trackBar1.Value = this.m_initialValue;
}
}
int m_initialValue;
}
Built the project.
Opened the default Form (Form1) that was created with the new project in design view.
Dragged the User Control that I had just created (UserControl1) out of the toolbox where it was automatically placed and onto the surface of the form.
The indicator on the slider bar appeared all the way to the right side (the correct and expected position given the default Maximum value of 10). Now, you tell me: What are we doing differently?
Try adding [Browsable(true)] .
The key portion of your question is here:
when dragging the custom control on a form
You're still in the designer, and the designer cheats a bit to render things. Does this still happen when you actually run the application?

How to refresh a winform custom control at design time after changing a property

Let's say I create a custom control which embed a trackbar. I also create an orientation property for my custom control.
When I drop the custom control on a form by default it will be horizontal. Then I set it to vertical, the trackbar should refresh to be vertical at design time.
How to do so ?
I think you should call Refresh() after changing the value:
public OrientationProperty Direction
{
get
{
return _direction;
}
set
{
_direction = value;
if (DesignMode)
{
Parent.Refresh(); // Refreshes the client area of the parent control
}
}
}
private OrientationProperty _direction;
Here's my solution to this issue:
1. Whenever you set something property, call Invalidate() in the setter.
2. After correspondent properties and refreshing method (for eg. overridden OnPaint) are implemented, rebuild!!! then you'll see the modifications taken effect in design time
3. During design, always check whether compilation errors are present, as this might stop VS performing all his tasks.
With this, when I put my control on a form, and adjust its own properties, refreshing happens immediately as expected.
PS.: old post, but at least verified the behavior in VS2015 too :)

My RichTextBox change backgroundcolor when Enabled is set to false

How can I set the backgroundcolor and fontcolor to be "normal" on a disabled (i.e. Enabled = false) RichTextBox?
Thanks
Windows User Interface guidelines demand that a control that is disabled appears disabled. With the obvious benefit that the user can tell that it won't make sense to keep banging the mouse on the control, trying to set the focus to it. Like all controls in the toolbox, RichTextBox implements this guideline as well. Overriding its painting behavior is not practical. Consider the ReadOnly property.
I would create a new control that inherits from RichTextBox. You could the override the BackColor property to always return something like white for example. Something similar could be done with the font color. Off the top of my head I think you could do something such as:
class CustomRichTextBox : System.Windows.Forms.RichTextBox {
public override System.Drawing.Color BackColor {
get { return System.Drawing.Color.White; }
set { base.BackColor = System.Drawing.Color.White; }
}
}
Though that may not work because you would probably have to override the OnPaint method to get around default greyed out behavior.
Another option would be to simply use the readonly property instead. ReadOnly is almost the same as enabled = false, except that you can actually still click in the text box (you just can't edit it). When it is readonly, you still have control over the normal color properties without having to override anything.
If you wanted to be even more creative, you could add a delegate to the Enter event of the RichTextBox that set the focus to some other control to prevent the user from even clicking in the box (which enabled doesn't let you do)
Emulate the property of being disabled. Implement a property that when set to false the control won't get focus or all key strokes are ignored.
Pretty bizarre in my opinion but the programmer wants what the programmer wants! ;-]

user control with a textbox

I have a user control with a textbox in a win forms application.
I would like to change the property of that textbox using the properties window of visual studio .
I am using that control in various forms of same project ,is it possible?
I have set the modifier property of text box as public and set following property in the user control:
public TextBox mytextBox
{
get { return textBox1; }
set { textBox1 = value; }
}
Thanks in Advance.
What is the intent of doing this? Are you trying to have "one TextBox control shared by multiple forms" (that is not really practical). However you can set up your forms in such a way as to have all forms update in response to a single change.
[TypeConverter(typeof(ExpandableObjectConverter))]
public TextBox mytextBox
{
get { return textBox1; }
set { textBox1 = value; }
}
Notes:
From the perspective of the PropertyGrid, the setter has no benefit in this case; the properties of the already-assigned TextBox are being modified in-place.
Remember to create an initial value, and to add the TextBox to the UserControl's control-collection. If you used the VS designer to create the TextBox, this should have been done already. If you find that the VS designer method InitializeComponents() is undoing your changes, create and add the control yourself.
You may have to rebuild the project and/or reopen the Forms designer for the change to be visible.
Off-topic: Use Pascal-case for properties, and the auto-implemented get;set; pattern for readability, if at all possible.

Categories