WPF: Anchor points don't work well sometimes - wpf

When I try to create a window using WPF (usually when the window is not re-sizable) this problem which has been shown in the below images happens. Although I can easily fix it by shrinking the inner frame a bit, I'm curious why it happens and in case it is a kind of Visual Studio form designer problem, why It's been happening for quite a long time.
Fixing the inner frame according to the designer view anchor points results in:

Don't position your controls absolutely. Remove the Height, Width, HorizontalAlignment and VerticalAlignment from your Border so that it takes the entire window. Then set your margin to an uniform one (Margin="10"). It will look perfect for all window sizes.
If you don't want to edit the XAML file manually, you can clear the properties in the designer by clicking on the small square named "Default" near every property.

Related

How to fix the order of items within a ToolStripContainer

I have a ToolStripContainer with a MenuStrip and a ToolStrip inside, both at the top. They're arranged as usual on Windows with the menu bar above the toolbar. Now, Windows Forms and DPI scaling support has always been a bit iffy. While everything looks fine at 100 %, I'm currently using 110 % DPI scaling and the menu bar and toolbar switch positions in the ToolStripContainer (I'd suspect it's the same with higher scaling factors, though):
My guess as to why this happens is that the designer places both controls at specific locations, even though they are arranged by the container, and with DPI scaling the ToolStripContainer gets locations for its children that would be consistent with placing the toolbar above the menu bar, as if someone dragged the bars around and reordered them (which is possible interactively, after all).
Short of replacing the MenuStrip with a MainMenu, is there a simple(ish) way of ensuring that regardless of DPI scaling the order of both remains consistent? I've got about 50 different windows to change in pretty much the same manner and would also rather avoid putting extra code into the codebehind file¹.
Things I've tried so far:
All changes in the designer have been applied at 100 % scale.
Change the z-order of the toolbar and menu bar in an attempt to control their order. This works with panels and docking, but doesn't apply to ToolStripContainer, apparently.
Docking the MenuStrip at the top. Doesn't work; the designer just removes Dock = None from the code and displays Top as the default value, but with scaling applied, it's back to Dock = None in the designer (and even without touching the Form in the designer, the result at runtime is the same).
¹ These are demo applications for a control library and the main point here is to keep the code clean and still providing a good experience out of the box. So a designer-only solution where the code is hidden away in already-awful code that no one reads would be preferable.
They are very frustrating components to work with. Because they can be dragged and moved it looks like the Location is the key, even though they behave a bit like they're docked. In OnLoad or OnShown have you simply tried resetting the desired location?
menuStrip.Location = new Point();
toolStrip.Location = new Point(0, toolStrip.Height);

How to use Blend to create a basic Grid

I'm a developer who's trying to get the hang of Blend. I've always used Blend to mess with control templates and such, but I'm trying to get the hang of using it for basic UI design, since I figure it's probably a bit faster than typing the XAML up manually in Visual Studio.
Right now I'm just trying to create a basic Grid, but I'm seeing two default behaviors that I'm hoping someone can show me how to change.
1) When I hover my mouse outside of the design surface, I see the temporary yellow line to show up, where the new Grid Column / Row will be when I click. The problem is that the newly created rows are set to heights like 0.2297* How do I get Blend to attach regular heights, like 250?
2) Ignoring 1), once I have some rows and columns, when I drag a button, or combo box, etc, onto one of the cells, it drops it exactly where I release the mouse, while adding some large margins to position it there. Is it possible to tell blend to just drop the control into the cell, and leave the margins alone?
Grids are awesome but it takes a bit of play to get proficient at working with them in Blend. Here are some tips to get you started (I cover this in detail in chapter 4 of my book).
1) When you use the snap lines to create rows and columns Blend automatically makes them relative (Star) sized, which is the behavior you are seeing. To change the row/column style to fixed (Pixel) sizes, click on the Padlock icons to the left and top of the desired rows and columns. Then, either edit the values in XAML or you can click near (but not on) the padlock to select the row or column. This will open the sizing properties in the Properties panel.
2) The short answer is "No". Blend will always add Margins when you draw the element in a cell unless you take care to draw them to the borders. This is too difficult and time consuming, so I just make sure I draw it somewhere inside my target cell. Now I can right-click the element and select "Auto Size > Fill" and the element will fill up the cell: no Margins, Width and Height set to Auto, and Horizontal and Vertical Alignments set to Stretch. [FWIW, addressing this is my number one feature request for Blend.]
I hope this helps.
To answer point 1) Blend is creating proportional grids so that the columns remain the same relative widths when you grow or shrink the grid rather than absolute grids. So if you want absolute grid widths you'll have to go in and edit the values by hand.
I find that it's easier to create the basic form in Blend and then tweak the values in the text editor - either in Visual Studio or Blend itself.
As for point 2) I've just tried this and as long as I click inside the column/row on the grid when placing a button it adds it to the correct column/row of the grid as expected. Select the button and then just double click inside the grid - this should add a button of default size where you clicked, but in the grid. (It would be much easier if I could see what you were doing).

Sizing WPF windows automatically

When designing WPF dialog windows in the XAML designer (that are not manually resizeable by the user), the windows automatically resize to fit their content, and everything is fine. But when I run my app, the windows become huge and there's a lot of empty space.
I know this is a "feature" of WPF that can be "fixed" by setting the SizeToContent tag, but another issue arises when I do this: If the window contains a textbox, for instance, and the user enters data that overflows the visible area, the window will stretch to accommodate it. This happens with listboxes, treeviews, you name it.
All I want is for Visual Studio to figure out the ideal window size that it shows me at design time, then set the window to be that size at runtime, and don't change the size after that. It seems like this should be an easy thing to do.
Edit: Figured out part of the problem: I have controls set up in a grid, and the column's width is set to "Auto" which is why everything is resizing.
Use View Box
The ViewBox is a very useful control in WPF. If does nothing more than scale to fit the content to the available size. It does not resize the content, but it transforms it. This means that also all text sizes and line widths were scaled. Its about the same behavior as if you set the Stretch property on an Image or Path to Uniform.
Although it can be used to fit any type of control, it's often used for 2D graphics, or to fit a scalable part of a user interface into an screen area.
<Viewbox>
<Enter your code/>
</Viewbox>
Try setting the window's height and width to Auto. Also, remove the SizeToContent attribute. This should fix it.
I do not think that this is this is something which is commonly requested so it's probably not easy to do, one method i can think of would be starting with automatic SizeToContent and handling the Loaded event and setting:
Height = ActualHeight;
Width = ActualWidth;
SizeToContent = System.Windows.SizeToContent.Manual;

WPF Tiled Background Misalignment

We have quite a complex WPF application (that I cannot show here) that somehow has the tiled background misaligned of one of its user controls. I was unable to reproduce this problem in a "clean" WPF project but will try to illustrate the problem in this picture:
(source: kintespace.com)
The gray area represents the user control and the black and red checks represents the tiled background inside the user control. The white background represents the window hosting the control. The VisualBrush is used here but the same problem comes with the DrawingBrush. I would prefer not to use the ImageBrush.
Can you open a "clean" WPF project and build something that will cause a tiled background to be misaligned like this?
You can do this if the layout root of the user control has a -10 left margin and a -10 top margin. the tiled backgoround in on the layout root of the usercontrol so, it looks like a alignment problem not a brush problem.
This problem is related to the tiled background cramming itself into the calculated height of the UserControl instance in the hosting Window. I am still unable to replicate this problem in a new project but it is "solved" (by stacking panels in the user control horizontally instead of vertically).
Here are two diagnostic techniques that can be useful in situations like yours:
Take your complex project, make a copy, and start tearing out large sections of code and XAML until the problem disappears. Then put the last section back and tear things out more gently. Repeat until you find the change that makes the difference.
Run the application, break where a local variable references your UserControl, then explore the visual tree just above and below your UserControl in the Locals or Watch window. Look at each Visual's internal properties VisualOffset, VisualTransform, and VisualContentBounds. These properties will usually clue you in to what property is being set incorrectly, and from there you can figure out why.

WPF - UserControl sizing on Custom Canvas

I have a custom canvas that I can drop controls on, move, and resize. I need to be able to at least start with a pre-determined size but then allow re-sizing.
My problem is that I have a user control that doesn't appear to resize. I set Height and Width on the user control (works on drop). But then as the control is resized on the canvas the visual size stays the same (the sizing handles are changing). I can see the Height property changing (usercontrol.height) as the control is resized. But again, the appearance of the control stays the same size.
I had a thought that the inner container on the user control should be bound to the usercontrol.height but that didn't seem to help. (or maybe I didn't have the binding right).
On the same canvas, if the dropped control is for example, an Image control, I can set an explicit height on the drop and everything resizes as it should. So it seems to be UserControl thing.
So is there something special I need to do with UserControls to get the visuals to resize? Should I be using explicit height and width to get it all started?
Thanks for any help.
The WPF layout system can be confusing, as you've discovered. There is no substitute for a solid understanding of the layout and measurement system. If you plan on doing much WPF development, it's worth taking 20 minutes to read this article on the layout system and then experimenting for a while in an iterative environment such as Kaxaml until you feel comfortable.
The system is very logical. It won't take long for the penny to drop. Sorry for the indirect answer, but I don't believe there's enough information in your question to really explain what's going on.
You might also look at the HorizontalAlignment and VerticalAlignment properties.
Not a WPF expert but I believe you need to enable auto-sizing in order to achieve the scenario you are looking for. This is done by setting the Height/Width of a control to Double.NaN which essentially says, "I have no specific size". Once you do that, the control should resize to occupy available space based on the need of the control.

Resources