C#: Reset Controls in a Panel (WinForms) - c#

What is a quick way to reset all the Controls inside a panel to their initial states (Compile-time state)? I have TextBoxes, RadioButtons, ComboBoxes, and CheckBoxes to reset. I'd like them to reset to the values when the program first ran. I'd like a solution that does not involve looping or recursion mainly because I don't want to reimplement the same thing over again when I start witha new project. I'm simply finding a set of methods to call that will do the job. Are there any?

Your controls have no compile time state, because state is a runtime concept.
I think you mean you want controls re-initialized to the state as shown on your property sheets. This state is applied by the generated code located in InitializeComponent, so to re-apply that state, you could just call it again.
The only problem is InitializeComponent also wires up events, and you probably don't want to do that twice. You could possibly work around this by deregistering all of your events before calling it, or by deduplicating the invocation list afterward (see this answer).
I don't recommend any of this. The best approach would be to write your own method that sets the properties the way you want them, one by one. Sometimes ya gotta write code.

Related

Getting Dynamic (Runtime) Buttons in WP7 to Associate with Objects

I am creating an interface for an XNA game and can't seem to figure something out. I'm new to programming, and feel like I have to be missing something obvious.
I'm creating a grid of levels, much like something you'd see in Angry Birds.
The number of levels will be variable, so I don't want to statically program them.
All of the buttons I use for level icons are created dynamically at runtime, based on a list of level objects. As I create the buttons I set up all of the click events to point to one method that is supposed to determine which button they clicked on, and load that specific level.
My problem is I can't seem to figure out a reliable way to actually tell which button they clicked on and associated that with one of my level objects in the list. I feel like I must be missing something extremely obvious.
Things I've tried so far:
As I generate the buttons dynamically I add them as children to a grid. So I tried using the index number of the sender as the index number in my list of levels (because they should both have the same number of elements).
For example:
App.CurrentLevel = PuzzleLevelsGrid.Children.IndexOf(sender as Button);
This worked great the first time I navigate to the level picking screen, but whenever I come back to it the children of my grid gets reset to a count of 0 for some reason, so it breaks down.
I've set break points and I can't explain how it gets set to 0. I load the children in my onNavigatedTo(), and sometime between the end of that and me pressing a button to load a level it gets wiped.
The other thing I tried was setting up a button object inside my actual level object, then when dynamically creating the level buttons I actually make changes to the button property in the appropriate level.
Then when I need to find out which button was the sender I just loop through all levels and match the sender to the button property. This method actually worked pretty well... until I started trying to load my levels using a background worker thread. The worker thread can't deal with the Button because it's a UI thread thing, and crashes.
Like I said, I'm a new programmer, so I welcome any and all feedback.
Thanks in advance.
The button, like almost every UI control, has a "Tag" property. This property has been designed for you, and only for you, so that you can put any value you like to identify the control.
For instance, you can put your level object in the Tag property of the button, then just read this value back in the click event.

What is the very last event fired off during creation of a silverlight page

I know this may seem like an odd question, but I am after the information queried in the title.
So far I have tried LayoutRoot.Loaded, but found that LayoutRoot.LayoutUpdated happens even later.
My motivation for this knowledge is the ability to have one component interact with another in code, but for this to happen I must be guaranteed they both exist.
Any ideas?
Clarification of what I'm attempting to do:
I have a collapsing gridsplitter control. From here
When the main page loads I make it collapse; which shrinks the object preceding it to width 0. If that object isn't 'loaded' yet then it doesn't collapse and the gridsplitter is in an odd state where it thinks it has collapsed the item but needs two clicks to effectively do that.
LayoutUpdated is the last event raised in the control object initialization timeline. However keep in mind that LayoutUpdated will be raised multiple time subsequently as required. Maybe you can share a little more detail on what you are trying to do.

How should the Form.Load event be used compared to its constructor method?

When initializing properties of controls or other values related to a Form I have a tendency to switch back and forth between initializing the values in the Form's constructor and then later when the Form.Load event is evoked.
What is the generally accepted usage of a Forms constructor vs it's Form.Load event? With other classes I would do all initialization in the constructor. Yet in in VS when you double click on a Form it jumps you to an event handler for the Form.Load event not the constructor. This leads me to believe that it's preferable to do all the initialization after the Load event instead of the constructor.
Yes, it is a wee bit sad that it works that way. It made a lot of sense at the time, now 10 years ago already. Windows Forms was targeted to be a replacement for VB6, the dominant point-and-click UI designer at the time. And Form_Load was important in VB6, that's where you customized the form view.
That wasn't really appropriate from the get-go, the Form class has a true-blooded constructor. And you can set control properties in the constructor before the actual native Window control gets created. There's a ton of code in WF to make that work. Code that the designer relies on, it sets these properties before the Load event fires. It is very efficient to do so, many controls get a lot slower when they need to be updated after their window is created. Like ListView and TreeView.
There are few reasons to not use the constructor yourself, like the designer does, especially since the C# IDE doesn't try to hide the constructor. Except one: you need the Load event when you write the kind of code that requires knowing the actual form size. That size isn't known until the window actually gets created, the Load event is the earliest after that. That ought to be rare.
And of course, if you do want to use Load then you override OnLoad instead of using the Load event. That would be another one.
When you double-click any control in the designer (including a form), you're jumped to the most common event handler for that control. That doesn't mean it's preferable to do anything there - just that someone's deemed it the most likely event handler.
A form's Load event typically happens after all of the controls have been created. The constructor happens beforehand. Depending on the logic you're implementing it might be beneficial to handle certain operations in one method or the other. For example, initializing many values is better done in a constructor: if the values effect the layout or content of the form, you might find that you're creating a "wasted" control hierarchy that's rebuilt when you change your values. Putting the initialization in the constructor might let the form build itself correctly first time - which is more performant and might avoid some errors.
Ultimately, both of those methods have their uses - look at what your code's doing and choose the one that's appropriate.
I always use the constructor and almost never the form.Load event unless I can't get away without. The reason is because the constructor can receive parameters when the Load event can't really.
It is so much more useful

How to fix nested winform control flicker issues

I am currently working on a program that uses a fairly complex structure of nested winform controls which changes dynamically as a user makes certain selections. To go into more detail about the specific layout of the controls would be to extensive for this question.
When ever a selection is made, a lot of updates are made to the underlying model which is controlled by the user controls. This then results in series of corresponding changes in the size/position/visibility of the displayed controls. All of these changes results in a painfully intense flickering of controls on the screen. I need to somehow fix this so that everytime the user makes a selection the screen is basically frozen until all of the control updates have completed.
I have attempted to use the Control.SuspendLayout/Control.ResumeLayout methods in many different places and ways and I can not eliminate the crazy flickering. I thought that suspending layout on the root control during the changes would fix the problem but it appears that this SuspendLayout doesn't help when child controls are changed.
Do I need to use some other approach rather than SuspendLayout? Is there a way I can debug SuspendLayout to see why it doesn't appear to be cascading to all of the child controls?
Suspend/ResumeLayout isn't your problem here. That only suspends automatic layout, the kind that is triggered by the Anchor and Dock properties. Double-buffering can't fix your problem either, that only suppresses flicker in each individual control. Your real problem is that you are updating too many controls at the same time, each will take its turn to paint itself and that takes time.
What you need is a different kind of double-buffering, compositing. Check out if the solution in this thread solves your problem.
In addition to #tommieb75's suggestion for double buffering, you can try and see if your root level controls have BeginUpdate/EndUpdate method pairs. These should help repress the repaints in between the calls.
If you are using WinForms 2+ then you can just set the 'Control.DoubleBuffer' property on the control to true (in the designer even).
With framework 2, setting DoubleBuffered sets the 3 flags : OptimizedDoubleBuffer, AllPaintingInWmPaint, and and another that I forgot, 'UserPaint' perhaps.
Also, do look at the BeginUpdate/EndUpdate as mentioned by #yetapb.
Use the SetControlStyles in the user Control, the flag is OptimizedDoubleBuffer which will prevent the flickering.

How to catch user changes in databound controls?

I have application full of various controls databound to my classes. I would like to ask user "You are closing application and you made some changes. Do you want to save your changes?". For this I need to recognize that user made any changes.
How to catch user made changes in databound controls? Is textBoxXXX_TextChanged the only way to do this?
Thanks in advance for all your answers.
It depends on the datasource; for example DataTable and DataSet sources contain the GetChanges() methods which allow you to easily see if rows have been added/removed/modified. Other data sources will have their own implementations, if any. If there is no implementation then it's up to you to determine how to check for those changes.
In any event this is something you should do at the data-level, not the UI (by watching for "changed" events). Watching events doesn't scale beyond a couple controls and maintenance can be iffy.
Update: Not sure why I didn't think of it, but a second option is to add a BindingSource to your UI object and use it as a databinding proxy (your UI controls databind to the BindingSource and the BindingSource binds to the real datasource). It provides a better approach than handling all your individual "Control_Changed" events, and requiring rework of your other layers (esp. if they aren't custom data-types).
You need to provide custom logic for that, there's not really an automatic way of doing this. As I see it there are several options:
At the start of the editing, save a copy of the original data object, and when you need to check, compare the current object with the saved one. The comparison can be custom (field by field) or semi-automatic by use of serialization (compare the serialized forms) - if it is serializable.
In each of your data object's property set accessors, test for a change in value and mark the object as 'dirty'.
As been discussed, there are many ways to do this depending on how granular you want to get.
A relatively easy way using client side javascript would be to do something like the following:
Hook into the onchange events of the form elements. You could do this dynamically on page load using javascript/DOM.
When the onchange error handler is called, you could set a page level variable: pageHasChanged = true;
Hook into the page's beforeonunload event (occurs when the user tries to navigate away from the page) and check the pageHasChanged variable to see if any changes were made. If changes were made you could alert the user.
This doesn't give you the detail of what changed, but would be fairly easy to modify to track which form elements changed.

Categories