Why do WPF Margins crop the control? - wpf

Please see the update
I have the following WPF controls.
<Grid>
<Label Content="Report Generator" Margin="0,0,0,294"/>
<TextBox Name="FilePath" Width="300" Height="25" Margin="10,30,207,264"/>
<Button Width="75" Click="Browse" Margin="335,30,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Height="25" Content="Browse" />
<Button Width="75" Height="25" Click="Extract" Margin="432,30,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Content="Extract" />
<ProgressBar x:Name="ExtractBar" Margin="10,70,107,204"/>
<Label x:Name="FirstEntityCount" Content="Number of Type1 Entities: " Margin="0,191,0,98" />
<Label x:Name="SecondEntityCount" Content="Number of Type2 Entities: " Margin="0,226,0,65" />
</Grid>
I've quickly thrown this together in Visual Studio 2012 designer. The target Framework is .Net 4.5 and this is a WPF Window. It's an addition to an existing solution.
The issue is that if I don't remove the 3rd and 4th margins (e.g. Margin="a,b,c,d", setting c and d to 0) and then specifying VerticalAlignment="Top" and HorizontalAlignment="Left" the controls are cropped.
See attached image below.
I can rectify this by setting the margins to be 0 and setting the alignments but I want to know why this happens by default? I literally have just dragged and dropped. The controls appear normal in Visual Studio 2012.
Running Windows 8 RTM.
UPDATE
My question isn't why the margins now work and why the didn't before (I get that they seem to be set so they crop the actual control itself); I'm merely asking why this complex IDE fluffs it all up... It's happened over 2 rebuilds...
From what I remember, it also happens in Expression Blend. I'll double check.

When you drag and drop from the designer, whether it be in Visual Studio or Expression blend, the designer will attempt to place the element in the exact location the control was dropped on the designer surface. When the designer places the element, margins are used to position the control relative to the containing element.
What is typically done when dragging controls onto the design surface is to reset the margins. In Blend and VS, you can reset any attribute to their default settings by clicking the little square in the properties and selecting reset.
Agreed that the setting of the margins by the designer is a bit of an annoyance; though, not really sure of how else this would be handled when using a visual designer to drag and drop.
Personally, I tend to switch between hand written XAML and the designer; lately, I've been using Blend much more since it can control the placement of nearly any element in the XAML by using the objects and timeline panel.
On a side note, to clean up the Blend XAML madness, install the XAML Styler extension for Visual Studio.

By setting the margins for top and for bottom, you are forcing the label to have a particular height. It happens that this height is not sufficient to display the height of the text that you have put in the label. I think if you reduce the bottom margin somewhat you'll find it fits OK.
On an unrelated note, wouldn't it be better to use Grid.Row and Grid.Column to position the controls on this Grid rather than having them all technically in position (0,0) and then using margins to position them?

Related

Sizing WPF controls based on Windows design guideline recommendations

How do I configure WPF to make its controls use the sizes recommended by Microsoft?
For example, a button should be 23 pixels high, including a 1 pixel transparent border. How do I implement the transparent border? Button.BorderBrush controls the visible border.
Another example is a single-line text box, which should be 23 pixels high.
Do I have to style everything by hand? Or is there way to cause the controls to default to a native Windows user experience?
Update: Here's a visual of some of the differences.
WPF controls:
Standard Windows controls: (from the Common Item Dialog, e.g. in Notepad, clicking File > Open)
This isn't a perfect comparison, since the in the Common Item Dialog, the file name box is a ComboBox, not a TextBox. I tried comparing the Print Setup and Print dialogs (also from Notepad), but they don't use the same size buttons or even the same font as the open file dialog. I keep forgetting that I'm dealing with Microsoft here, not Apple.
There is a distinction regarding the button that is consistent through all of Notepad's dialogs, which WPF doesn't match by default. If the button is a default button, the border is thicker in Notepad. The button's transparent border turns blue. For a Notepad non-default button, you can click one pixel outside the visible border and still hit the button. This doesn't work for the WPF button.
Flexibility is nice, but native it-just-works-and-looks-great controls would be really nice. If there's a drop-in solution where I don't have to think about this stuff, that would be great.
Here's the XAML for the WPF controls:
<StackPanel Name="controls" Margin="20">
<TextBox Text="Default TextBox" />
<TextBox Height="23" Text="TextBox with height 23" />
<Button Content="Cancel" />
<Button Height="21" Content="Cancel" IsDefault="True" />
</StackPanel>
And the code-behind:
foreach (Control control in controls.Children) {
control.Margin = new Thickness(0, 10, 0, 10);
control.VerticalContentAlignment = VerticalAlignment.Center;
}

Elysium style destroyed when using WindowsFormsHost

I'm using Elysium in my wpf application to get a metro styled interface. However the style is not preserved when I try to use Windows forms control.
Example:
<Grid>
<RichTextBox />
</Grid>
Gives a perfect result (with the thin white border around the wpf control)
However:
xmlns:WinForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
.
.
<Grid>
<WindowsFormsHost Name="wfh">
<WinForms:RichTextBox />
</WindowsFormsHost>
</Grid>
Gives me a different look with the legacy windows form type of border.
I want the thin white border around my WindowsFormElement if possible. I'm out of ideas at the moment.

wpf controls traveling around the grid/stack panel and not staying put

I am building a user control in WPF and put a few buttons in a stackpanel laying inside a grid. Problem is that when I build the app and run it, the buttons "sail around" and don't stay where I put them in the designer window. Is there any attribute I'm missing(or some sort of container?)?
Thanks.
Try setting the alignment properties of your grid:
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
...
</Grid>

AdornerDecorator - what does it matter where they are placed?

With some xaml like this:
<Grid Name="grid">
<AdornerDecorator>
<TextBox Height="23" HorizontalAlignment="Left" Name="textBox1" Width="120" />
</AdornerDecorator>
</Grid>
The WPF Snoop utility indicates textBox1 is a child of AdornerDecorator (as you would expect) but also that the AdornerLayer that AdornerDecorator creates is also a child. As a custom adorner added to the AdornerLayer can be displayed 'outside' the textbox, the AdornerLayer's drawing surface must stretch outside too (presumably all over the window).
So, what real significance does the placement of AdornerDecorator have (given we bind a UI element to the custom adorner, which we place in the AdornerLayer)? I know AdornerLayer.GetAdorner(textBox1) will get the first adorner layer in the visual tree up from textbox1, but what does it matter where that is (as the custom ardorner gets added to the layer and the custom ardoner knows which element it is bound to)?
The short answer is that it matters when you start to deal with controls that overlap other controls (in the z-index plane) and you care about whether or not a particular adorner layer shows on top of the overlapping controls. For example, when you use an ErrorTemplate, its contents get rendered in an adorner layer and if you don't supply an <AdornerDecorator> in your app (meaning that you just use the one provided by most Window templates), then you can end up with this happening.
By placing the <AdornerDecorator> where we want, we can control how this overlapping behaves.

Bring closer Items in ItemsControl

I have an Itemscontrol, witch contains two items after the Binding.
My problem is that the second item is getting out from the window's area.
My question is -
how can I bring closer the Items's texts without reducing the font size or increasing the window's height ?
Is there something like the padding and marging of HTML ? or maybe some other trick?
p.s - the font size and the height of the window must not be changed.
This is how it looks:
(source: timg.co.il)
And this is the code:
<UserControl x:Class="WpfApplication4.AnnouncmentsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="86" Width="300">
<Grid>
<ItemsControl Name="announcmentsListBox" ItemsSource="{Binding}">
</ItemsControl>
</Grid>
Your TextBlock has a height set of 40 units. If you remove that attribute altogether, you'll see the items spaced more naturally.
So your XAML would look more like this:
<Grid>
<ItemsControl Name="announcmentsListBox" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Text}" />
<Button />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
I would advise you to use Mole visualizer to examine the generated items. Mole 4.2 can be downloaded from http://karlshifflett.wordpress.com/mole-for-visual-studio/
Just need to copy "Mole.Visualizer.dll" to appropriate visualizer folder.
If you are developing on Vista and are
running with Elevated Security
enabled, you must install Mole in the
following directory.
* {VS Install path}\Common7\Packages\Debugger\Visualizers
All others download and unzip the
above package. Copy the file in the
Release package to either:
* My Documents\Visual Studio 2005\Visualizers {VS2005}
* My Documents\Visual Studio 2008\Visualizers {VS2008}
You can set a break point somewhere in the code which is easily accessible and then start the Mole visualizer on some object. Navigate the visual tree to the itemscontrol. Look for values in Margin and Padding for the generated TextBlocks. It will also tell you whether the values are inherited or local etc.
Use a Padding set to 0. Also, you can set Negative Margins which in many cases is the only way to coerce text into certain layouts (where Padding doesn't fit the bill, and container layout is non-overridable.)
You can also implement your own items panel template and redefine the layout of each item to compensate for the the padding being introduced, but this shouldn't be necessary. It would, however, afford you control over layout calculation for all items so that you can best-fit each item (and even go one step further and implement crazy new item layouts such as a carousel, as has been demoed by many pre-RTM videos of WPF/Avalon.)
Hope that helps, it's what I do.

Resources