Sizing WPF controls based on Windows design guideline recommendations - wpf

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;
}

Related

Mouse hit lost on popup menu transparent background in xaml

I have run into a very strange issue today:
I have a popup menu that opens when I hover above an image. The popup menu is positioned right of the image.
this popup menu is templated to look like a rectangle with a little arrow pointing to the image
the menu contains clickable elements, so I need to be able to move the mouse from the image to the menu without it closing in between, and this is where I get confused: if I move the mouse right over the tip of the arrow and then the menu, everything works fine. If I move the mouse over the transparent space between the image and the menu (above or under the arrow), the menu disappears.
Here is the template for the menu:
<Popup AllowsTransparency="True" Name="c_popup" Width="300" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Data="M 0 10 L 10 0 10 20 Z" Stroke="#252C37" Fill="#252C37" Margin="0,18,0,0" Grid.Column="0" />
<Grid Grid.Column="1" Background="#252C37">
<TextBlock Text="{Binding Name}" Margin="20,10,0,0" FontSize="18" Foreground="White" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" />
</Grid>
</Grid>
</Popup>
you'll notice that I specifically put Background="Transparent" and not Null (I am aware of the effect this as on the hitTesting, see this question)
funny thing is, though: If I put Background="#01000000", it works as expected. (And I get almost what I want, since this is almost a transparent background)
but I would still like to know what is going on there...
I suspect it has something to do with the fact that this is a popupmenu. I assume WPF does something to remove the hitTesting on any surface that is transparent in a popup menu, either when the background is null (which is expected) or even if it is specifically set to transparent (not expected). Can anyone confirm this?
Converting my comment to an answer.
This seems to be more of a "Windows OS" issue than WPF specifically in the way AllowTransparency="True" at a Window level makes the system ignore the element for mouseover events when Background="Transparent" or Opacity="0" on the element..
A detailed explanation of this behavior can be found Here
Adding the MSDN answer just in case the link goes missing later:
Windows supports transparency at the HWND level through a feature called "layered windows".
Layered windows are represented by a bitmap.
The Operation System(OS) renders the bitmap whenever it needs to.
For the OS need to respond very quickly to mouse movement, Windows uses a dedicated Raw Input Thread (RIT).
RIT runs in the kernel and handles the singals from mouse hardware.
RIT can scan over the HWND hierarchy to detect which window the mouse is over.
For normal windows, the RIT checks the mouse position against the window's rectangle.
For layered windows, the RIT looks in the bitmap that specifies the content for the window and checks the effective transparency at that location. The effective transparency can be affected by opacity, color and alpha channel.
If the pixel is 100% transparent, the RIT skips the window and keeps looking. This point is the reason that MouseMove event is not fired.
If the Background of window and control are both Transparent, all the pixels that represent this control(Canvas in your example) in the layered windows are totally transparent. As described above, RIT will skip them and never send WM_MOUSEMOVE message.
So if you want only show up the control only when the mouse is over and otherwise and the window is transparent, you have to make the control not 100% transparent.
Something to note in this case is, even though Popup is within a Window that does not have AllowTransparency="True", Popup generates a Chrome-less window itself and the AllowTransparency="True" on the Popup affect this new chromeless-Window the same way as mentioned in the MSDN link above.
If this control were just a standard control like Button/Rectangle... then just setting the Background="Transparent" would make it work fine and not have this issue.

Why do WPF Margins crop the control?

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?

Silverlight toolkit sets styles for grid, not just actual control

I've just installed the Silverligt toolkit 4 to get access to some of the nicely styled controls.
However, when I surround a button in a grid with the theme, I get the following result:
http://screencast.com/t/aiWsArdb
Both of the squares are grid controls, with a solid color background. But when I apply a theme to the button in the left grid, the entire grid gets styled. That's not really what I am after. Anyone know how I can avoid this? Basically I just want the theme to apply to the button only, and not the parent grid.
The XAML is:
<dark:ExpressionDarkTheme><Button Content="Button" Name="button1"/></dark:ExpressionDarkTheme>
The ExpressionDarkTheme has a default Black Background, try setting it to null.
<toolkit:ExpressionDarkTheme Background="{x:Null}">
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
</toolkit:ExpressionDarkTheme>

Lockable Surface in WPF

I want a custom Control in WPF which have a appearance similar to HTML, we use for showing Images in the centre of the screen with the whole screen locked and only image is showing.
I dont want to show images, I want to show UserControls within this section.
Can someone give suggestions of this?
In your Window, put all your controls in a single Grid, with a Border control (that contains your image) as the last item in the Grid (which means it will display on top of the other items). Toggle its Visibility via binding or code. Adjust styles as required.
<Window>
<Grid>
<!-- window controls go here --->
<Border Visibility="..." Background="#80000000"> <!-- EDITED -->
<!-- overlaid image (and/or other controls) goes here --->
<Image
Source="..."
Width="..."
Height="..."
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<Grid>
</Window>
In Windows applications this is generally achieved using a modal dialog, i.e. you create a normal WPF window and show it using ShowDialog.

Get string under a mouse hover from wrapped Silverlight TextBox

when hovering my mouse over a wrapped textbox, I want to get the word or text position immediately under the mouse.
I've seen some samples for a single textbox, like this one, but I have a wrapped textbox.
I think I might be able to do this if I had a MeasureString function but I don't have that either in Silverlight (would be useful for other things).
Example TextBox
<Textbox TextWrapping="Wrap" Width="50" Text=" ... " />
There isn't this ability in Silverlight today. Here's what I would do as a workaround:
Have an invisible (Opacity 0, IsHitTestVisible=False) WrapPanel with a TextBlock for each word.
Make the WrapPanel the same size as the TextBlock
Adjust margins on the TextBlocks and WrapPanels until you get similar spacing.
Do hit testing on the WrapPanel with the TextBlocks to determine the word

Resources