C# Winforms Enable/Disable button based on function - c#

I want a button on my winform to be enabled or disabled based on the return value of a particular function. Basically, I'm trying the following code in various places where the function will possible return a different value:
btnNewNotices.Enabled = isSelectedPrinterValid();
this.btnNewNotices.Refresh()
However, this is not working. Why is it when I call the refresh method after the enabled property is changed, that the button does not become enabled? I have to close the form and reopen it before the button properly disables. What is the best way to accomplish what I need here without having to bounce the form?

you can add a Databinding for the Enabled property.
if your method is implemented in your Form then you can define a Property
public bool IsSelectedPrinterValid
{
get{ return this.isSelectedPrinterValid(); }
}
And add a Databinding as following:
btnNewNotices.DataBindings.Add("Enabled", this, "IsSelectedPrinterValid");
You can refresh your value:
btnNewNotices.DataBindings[0].ReadValue();
The common way is to implement a ViewModel containing all Properties and Methods you need and bind your controls to these.

Short answer, but it's pretty straight forward.
Using .Refresh(); causes the button to repaint itself, and resets the Enabled property. There's no reason to use it in your context. Just remove it.
btnNewNotices.Enabled = isSelectedPrinterValid();

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.

Binding between controls in Windows Forms

Is there a way to make a control dependent on another control? I have a combo box and a button, and I need the button to be enabled if and only if there is an item selected in the combo box.
I know I can set the Enabled property of the button inside the SelectedIndexChanged callback, but then it will require some code, and besides there's an issue with what initial state the button would have. So I'm looking for something that wouldn't require manually handing events, is this possible?
Thanks!
No, there is no way in winforms to do this without code. What I usually do is to collect all such state-setting code into one specific method:
private void SetControlStates()
{
theButton.Enabled = theComboBox.SelectedIndex >= 0;
// code for other controls follow here
}
Then I trigger this method from all over the place, as soon as there is an interaction that may lead to the state changing (including the last thing I do when the form has finished loading; that takes care of initial state). If you want to avoid unnecessary assignments, just add code to check the value first:
private void SetControlStates()
{
bool buttonEnabled = theComboBox.SelectedIndex >= 0;
if (theButton.Enabled != buttonEnabled) theButton.Enabled = buttonEnabled;
// code for other controls follow here
}

Silverlight business application initialize check

I am using the Business Silverlight application. I have incorporated some MVVM into this and were off an running with it. We are using some telerik controls, mostly the ribbon control and the docking. We register all the telerik ribbon controls in the about.xaml.cs file, the method is DisplayUI - its here where we register the docking control then we register the ribbon after this. What happens is that when you click the ABOUT link it shows our first tab with buttons(perfect). when you click the HOME link next to the ABOUT link, we go back to the home page..but when you click the ABOUT link again it registers the controls again so we end up with two tabs that are the same.
Is there a way to check to see if this about.xaml.cs file has already been initialized? Im guessing that is has a handle on the first call in memory as I am able to see the first tabs rendering..
Thanks
here is the about code
public About()
{
InitializeComponent();
DisplayUI();
this.Title = ApplicationStrings.AboutPageTitle;
}
that display UI does all the work in registering the dockpanel and the ribbons. We'd like to not have the DisplayUI() called if this has already been rendered once.
If you do it by event handler can you unsubscribe from the event at the end of the method? Without seeing some code it's hard to work out what to change.
It's not the nicest way of doing it, but if this code needs to run once and only once then you could have a static boolean variable on the class set to false and when you call DisplayUI you check the value of this. If it's false you set it to true and run the method, and if it's true you just return.

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 :)

Disabling a control from receiving a event in C#

I have a dialog with loads of control in it. Each and evey control will be populated during the loading sequence and it might take a while for it to get completely filled. Mean while, I don't wanna allow the user to click on any of the controls. In other words, I wanna disable the control from receiving the events and I don't wanna disable the controls (as it might look odd).Also, I don't wanna subscribe and unsubscribe for the events regular intervals. Is there any way to stop the controls from listening to the events for a brief time ??
Sudarsan Srinivasan
The whole point of disabling controls is to communicate to the user that the control cannot be used at a particular time. This is a convention that users have learned and are used to, so I would advice to follow that. Not doing that may confuse the users.
The easiest way is to disable the container in which the controls are located in, rather than disabling each and every control. A better way (or at least the way that I prefer) is to have a method that will control the Visible and Enabled properties of controls based on which state the UI is in.
The easiest way is to move the control population out of the load event (if possible). Then in Load do something like:
private bool _LoadComplete;
void OnFormLoad(Object sender, EventArgs e)
{
_LoadComplete = true;
InitializeControls();
_LoadComplete = false;
}
void InitializeControls()
{
// Populate Controls
}
void OnSomeControlEvent()
{
if (_LoadComplete)
{
// Handle the event
}
}
Edit A Couple other Ideas:
Set the Application.Cursor = WaitCursor (typically will disallow clicking, but not a 100% guarantee)
Create a "Spinner" control to let the user know that the screen is busy. When loading bring it to the front so it sits on top and covers all other controls. Once you're done loading set it to visible = false and show your other controls
Unfortunately the only way i know of is to have a class variable (called something like _loading) and in each control handler do something like:
If (! _loading )
{
...
}
And in your loading code set _loading = true; once you have finished loading.
If you just want to disable user input, then you can set the form's Enabled property to false.
This has the effect of blocking user input to any of the form's controls, without changing the appearance of the controls; it's the technique used internally by the ShowDialog method.

Categories