When designing WPF application UI's in XAML, should every container-type control contain a layout control to house all children controls?
Take a group box, for instance. I can either throw controls onto the group box directly, or I can use a layout control and place the layout control inside of the group box and then controls in that.
I can see the benefit in the latter because the layout control represents a set of well-defined rules for how the children will behave. In doing this, however, my XAML tree starts getting deeply nested and a little harder to navigate.
Given this, is it best practice to always use layout controls or are there cases where it is perfectly acceptable to throw a control inside group boxes and tab items without such? What would be the negative implications of this if any?
There is no negative implications in using Layout panels because even if you havent specify one, there is a default one in the VisualTree. If you don't use one explicitly, your XAML may looks cleaner.
Most of the ItemsControls have a StackPanel as the default Layout. So it is basically a question of whether you want a StackPanel behavior to arrange your child items or not?
Jobi is correct that there are really no implications either way, but my gut instinct has always been to use a Container to hold multiple controls. A lot of that is driven by my need for highly structured organization, but mostly it just makes sense to me.
I do end up with a lot of nested Grids, StackPanels, etc. Yes, the tree can get pretty deep, but I use Blend almost exclusively for layout and design, so navigating the tree is not so bad, especially if you remember to give everything good descriptive names.
I don't know if it's "Best Practice" but it certainly works best for me.
Related
I have a wpf grid setup where I have two custom buttons that are next to each other. First picture is how the design window looks like, however, functionally, it looks like the second picture. I want them to function like the grid doesn't block them (closely resembling the first picture.)
The current xml I have is based on this MSDM which is very basic.
I do not know how to proceed. Do I have to use a different control panel/container or is there a setting to allowed them to extend passed the grid if the other button isn't above it (like zpanel?)
E: I couldn't find any other questions for this, so please link to any searches/posts with information on it.
Turns out I can use canvas and just do a bit more xml to keep the design the same. I would still like to know if it is possible to overlap them in any way for future use.
I use a Contentcontrol to show the user controls of the program, Now there is a problem for me to close the user controls After searching, I found an example that The user controls is loaded on a DockPanel
Now my questions:
What is the difference between these two controls? (Dockpanel vs ContentControl)
Is it okay to use this control(dockpanel) Instead of Contentcontrol to display application user controls?
Is there a similar code for Contentcontrol?
ucChild ChildWindow = new ucChild();
ChildWindow.ParentControl = this.UIPanel;
UIPanel.Children.Clear();
UIPanel.Children.Add(ChildWindow);
Standard disclaimer for people coding WPF like it is WinForms: First off; direct UI manipulation like this is a bad idea. You should
be modifying a view model and allowing the binding system to update
the UI. Use the MVVM pattern; WPF will work for you instead of
against you
To your actual questions:
Everything. I mean; they both inherit from FrameworkElement but that's about it in terms of commonality.
A DockPanel is as the name suggests, a Panel. That is; it controls the layout and sizing of one or more child elements. Specifically, DockPanel is good at situations like the following: you want an element to use up a full column of width, then another span the top (except for the previous element) and have the last element fill the remaining space.
A ContentControl is basically a placeholder, its purpose is to expose a settable (and most importantly, bindable) Content property that you can stuff another control into. Even better; you can put an actual object there and use a DataTemplate to control the display (this approach would conform to MVVM).
You can't really replace one with the other, see above
No. ContentControl is not a Panel and so does not have the Children property.
I'm creating a Windows 10 Universal app, there are two panels in my main page.
In tablet/desktop mode, both are visible at the same time (just two simple Grids, one fills the left side and the other one fills the right side)
However, in phone mode, there's a pivot and user can swipe between panels.
(I could use SplitView and hamburger menus which work easily in both Tablet/Desktop and Phone modes, but a pivot makes more sense in my case)
So, What I currently did is, I have two instances of each panel. PhonePanel1 and PhonePanel2 are two grids inside two pages of my pivot control, and TabletPanel1 and TabletPanel2 are two grids which can be shown side by side. and I use AdaptiveTriggers to detect page width and switch between these two view methods.
However, having two instances of each panel is not a good approach, because those are showing basically the same content.
Is there any better approach to do this? Maybe changing Grid's parent when triggers are changing view mode? or something better?
The only way to change the parent that I can think of is to write some code behind that will render them in the new location. A suitable solution may be to defer the loading of the controls until they are needed.
x:DeferLoadStrategy=”Lazy“
If you add this property to your controls that are duplicated, they will only be loaded when required. So on a phone the PC/Tablet view should never be loaded, unless the user is running in Continuum on an external display.
On a PC you may still end up with both loaded (If the user resizes the window) - On a PC there are usually more resources so it's less of a problem there in most cases.
I looked into the code behind approach to move the controls to a different parent and I think honestly it's premature to do that when it might not even improve performance.
I have gone for the Defer Load Strategy property and found performance to be fine, and it requires very little code. My duplicate controls are sharing the same ViewModel so I pretty much just added the property to ensure resources are only used when essential.
There is nothing wrong in your approach. To reduce memory usage, when adaptive trigger happens for example on the phone, set TabletPanel1 and TabletPanel2 visibility to collapsed.
If all panels use the same datacontext then leave it as is, if not set datacontext for collapsed controls to null.
You could create each of your panels as user controls then you've only need to define the contents once but each control could be included in each of the layouts you want.
Situation: I am making a Collapsible Panel. In my business situation, I am required to have the panel support the following:
A "direction" (ie, will it dock top, bottom, left, or right). This changes which direction it collapses and a few other things.
A "style". There are some predefined visual styles for this product (defining background color, gradient or not, text color, hover color, etc).
Here's the problem: certain styles are incompatible with certain directions. Here are the requirements:
There needs to be some way to prevent/warn the programmer if he/she coded the panel to have incompatible style and direction. For example, having the panel throw a runtime exception if they are incompatible will satisfy this requirement.
Not allow anyone to dynamically change either style or direction during runtime. If I need to, then I can allow it to be "dynamically" changed in InitializeComponent, but not anywhere else.
The panel needs to be visible in Design View. but not necessarily able to be dragged and dropped in design view, and technically I don't need to even alter the attributes of the panel in design view. Though I obviously want either of those other things if possible.
One potential solution: Have the constructor take two inputs: a direction and a style. That way both the changes are treated as an atomic action. If they are not both changed at the same time, then between changing the direction/style and then changing the other, the panel will be in an inconsistent state. I want to avoid that.
How can I get the Design View to not use the default constructor and/or what are better practices for fulfilling the requirements?
Note
The Panel is only an example and a use case to ask the broader question. I want this post to answer the direct question on the best practices for getting the Design View to handle my requirements. If the Visual Studio supports injecting a non-default constructor in InitializeComponent, then I want to know how (and any caveats with that). If there are better practices which fulfill the listed requirements, then I would like to know that as well.
Add support for the ISupportInitialize interface which the designer can use to set all the properties and tell you when it's finsihed.
Partial answer: you can't make Designer use some custom constructor. You will need to put the logic in property setters.
Throwing exceptions there might lead to messy Designer errors. How about resetting fields to some proper state instead?
You will probably need to differentiate the behavior depending if you're in DesignMode. If you haven't already, take a look at DesignMode considerations.
Here's a screenshot of my application:
Basically, depending on what option is selected I'd like to show another 'content' which can be a buttons, or forms or whatever.
What would be the best choice for this? Using MDI? I'm really new to this type of thing.
This scenario lends itself well to tab pages, as you'd find on a TabControl.
However, since you already have a mechanism for switching between the content, you might prefer to create a series of Panels whose Dock property is set to DockStyle.Fill. When the user clicks the appropriate heading, you simply need to show the appropriate panel and call BringToFront() on it. This is essentially what the tab control does internally, anyway.
Don't forget to use SuspendLayout() and ResumeLayout() appropriately to reduce flicker, which can be a huge problem in WinForms applications, especially when there are lots of controls.
You can position a TabControl where the buttons are not visible and control it from your buttons.