Yesterday I found out that when you need to create controls at runtime, you can use the LauyoutEngine to place the controls at the right location. I always used the TableLayoutPanel for this, but I must say, the LayoutEngine works better and I have more control now.
But I was wondering, how does this work under the hood? When is the LayoutEngine property invoked? And when is it a best practice to use the layout engine?
The LayoutEngine property is accessed/created (and cached!) in the (base) constructor of the Control. So if you want to use it, you need to subclass Control or Panel and override LayoutEngine.
Try to avoid it. Your UI component:
is fairly simple ? Don't use it, you'll shoot yourself in the foot.
is getting more complex ? Try to solve it by compositing multiple panels, they get you quite far.
might be re-used somewhere else ? Try not to use it, you won't get all the different layout use-cases right (Padding/Margin/DockStyle/DockPadding/Anchors/AutoSize/AutoScroll/...) and it'll be a mess.
Maybe, if your UI component
is a composed out of more inner controls
you're trying to do something fancy and need more control
none of the inner controls should be accissible/extended
you're willing to spend more time than figuring out why your TableLayoutPanel/FlowLayoutPanel/... doesn't layout the way you want it to
... then by all means, give it a shot! You could get some quick results, but you'll find yourself rewriting the layout method more than you'd like.
Related
In the system I'm working on we have a lot of grids, with very repetitive behaviours and properties. I'm going to make refactor and separate those to one common control that can be used in the whole system.
But I have a doubt - use CustomControll to achieve this, or UserControl?
Custom Control - I do not need to overwrite OnPaint at all, so it's a bit overkill. But on other hands - this control will be indeed a special case of Grid control, so inheritance seems to be natural chose.
User Control - it seems to fit better to make "some system control with preset properties and behaviors", but it will be containing only one child - the grid control. No composition. So it seems that using user control here is not what creation of User control mechanism had in mind
So what You guys think? It's better to use CustomControl, UserControl, or just throw programming away and became a monk?
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.
My program will prompt the user for a number, i.e. 25. The program will then start the "main form" with 25 controls (textbox). The 25 (or whatever number) of textboxes (or whatever control) will need to be formatted evenly. I will also need to be able to retrieve the text (or another property if I use another control) in order, from left to right and up to down. What is the best method of approaching this?
Using WPF MVVM. In a .XAML file, create a DataTemplate with the DataType of a ViewModel that will provide the binding for your TextBoxs, lets call this the TextboxViewModel. Then using a ItemsControl element with an ItemsSource of TextboxViewModel. You'll be able to instantiate as many TextBoxs as you want and be able to get the result by browsing through your list of TextboxViewModel.
Supposing you are using Windows Forms here.
Dynamically create the X controls and add them to the Controls collection of your form. To ease the access to them you can store their reference in a List and set some event handlers too, depending on your needs. You just need to calculate their positions while you add them.
If WinForms, this is exactly what the FlowLayoutPanel is for. Just add the controls to it and they will arrange themselves automatically, wrapping down to the next row as needed. As Mihai already suggested, you could also keep reference to those controls in a List.
Another option would be to use a TableLayoutPanel. It's a little more difficult to learn and use, but is much more flexible and powerful.
I am currently faced with a trivial task but I can't think of a solution.
In order to explain the theory of how it should work ...
There is a form of authentication. http://prntscr.com/pwat5
This form fits on TabControl -> TabItem and TabControl in turn is placed on the component Grid.
Actually, on that key input is an event by clicking authenticate and change the login form to another form.
Such forms of authentication, I need more, I went for it in the following way and laid the form data to a specific component, the structure looks like this:
Grid
ListBoxItem
MyAuthForm
... //Well, actually imposed on the rest of the crap form MyAuthForm
For an identical copy of my form MyAuthForm I clone the object, and to be more precise, I clone ListBoxItem together with all its contents to the new object and thus add it to the component Grid, that is, get a new cloned object.
Grid
ListBoxItem
MyAuthForm
... //Well, actually imposed on the rest of the crap form
ListBoxItemСlone
MyAuthFormСlone
... //And so on
But the problem is that my original object carries a variety of events but the cloned object can not deliver on certain events in the original.
How is it possible to solve this problem? To clone an object somehow could refer to the events of the original object?
In general, explained as best I could, I hope most accessible outlined what I want, thank you very much for any hints and ideas, the second day I suffer with this case and so far no ideas.
ps In the manual for each cloned object, I can not create events for such forms of authentication can be more than enough, everything has to be fast, so the only option is to somehow refer to already existing events, wpf allowed for that possibility?
Perhaps since you are working with WPF, if you bind the events to commands or any other mechanism then the cloned window, given the same datacontext would target the same methods and your problem would be solved.
I hope i understood correctly.
In the past i used Caliburn with WPF and there was something called ActionMessage there that might be of use to you.
It bubbles up through datacontexts until it finds a method with the specified name or else it throws an exception. Maybe you can use this, coupled with the fact that the 2 clones share the datacontext instance to enable you to make them all point to the same authentication method.
Hope i got it right.
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.