i'm trying to figure out how to layout a simple dialog in WPF using the proper dialog units (DLUs).
What's a dialog unit?
A dialog is a unit of measure based on the user's preferred font size.
A dialog unit is defined such that the average character is 4 dialog
units wide by 8 dialog units high:
This means that dialog units:
- change with selected font
- changed with selected DPI setting
- are not square
i spent about two hours dimensioning this sample dialog box from Windows Vista with the various dlu measurements. Can someone please give the corresponding XAML markup that generates this dialog box?
alt text http://i44.tinypic.com/30a7390.jpg
(Image Link)
Now admittedly i know almost nothing about WPF XAML. Every time i start, i get stymied because i cannot figure out how to place any control. It seems that everything in WPF must be contained on a panel of some kind. There's StackPanels, FlowPanels, DockPanel, Grid, etc. If you don't have one of these then it won't compile.
The only XAML i've been able to come up with (uing XAMLPad) so far:
<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Image Width="23" />
<Label>Are you sure you want to move this file to the Recycle Bin?</Label>
<Image Width="60" />
<Label>117__6.jpg</Label>
<Label>Type: ACDSee JPG Image</Label>
<Label>Rating: Unrated</Label>
<Label>Dimensions: 1072 × 712</Label>
<Button Content="Yes" Width="50" Height="14"/>
<Button Content="Cancel" Width="50" Height="14"/>
</DockPanel>
Which renders as a gaudy monstrosity. None of the controls are placed or sized right. i cannot figure out how to position controls in a window, nor size them properly.
Can someone turn that screenshot into XAML?
Note: You're not allowed to measure the screenshot. All the Dialog Unit (dlu) widths and heights are specified.
Note: 1 horizontal DLU != 1 vertical DLU. Horizontal and vertical DLUs are different sizes.
See also
- WPF applications that adjust to screen and font settings (Or, How would I relate DLUs to units in WPF?)
- WPF global font size
- WPF buttons same/recommended width
- WPF version of .ScaleControl?
- Microsoft User Experience Guidelines: Recommended sizing and spacing
- Microsoft User Experience Guidelines: Layout Metrics
Bump: 6/20/2011
The following XAML will give you the effect you are looking for.
Note that I have doubled the DLU units in the markup - thus keeping the same aspect. It looked funny having a Button height of 14units. You may need to tinker with the figures presented in the market.
Also, I started to remove some of the "Vista Layout" into separate styles. You may be able to continue down this path so you have quite a reusable set of styles which follow the Vista guidelines. I'm fairly sure some other people have done something similar.
Furthermore, I took some liberties with the size of the dialog. You mentioned you wanted 210x96units - you would need to set this amount, plus the window chrome.
Anyway, on with the content:
<Window x:Class="VistaLayout.Dialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Delete File"
ResizeMode="NoResize"
Height="212" Width="430">
<Window.Resources>
<Style x:Key="FooterButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="28" />
<Setter Property="Margin" Value="8,0,0,0" />
</Style>
<Style x:Key="FooterPanelStyle" TargetType="{x:Type UniformGrid}">
<Style.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource FooterButtonStyle}" />
</Style.Resources>
<Setter Property="Rows" Value="1" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</Window.Resources>
<DockPanel Margin="14">
<!-- Footer -->
<UniformGrid DockPanel.Dock="Bottom"
Style="{StaticResource FooterPanelStyle}">
<Button>_Yes</Button>
<Button>_No</Button>
</UniformGrid>
<!-- Main Content -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Width="64" />
<StackPanel Grid.Column="2">
<TextBlock Margin="0,6,0,14">Are you sure you want to move this file to the Recycle Bin?</TextBlock>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="14" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Width="60" />
<StackPanel Grid.Column="2">
<TextBlock>117__6.jpg</TextBlock>
<TextBlock>Type: ACDSee JPG Image</TextBlock>
<TextBlock>Rating: Unrated</TextBlock>
<TextBlock>Dimensions: 1072 × 712</TextBlock>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</DockPanel>
</Window>
As with most XAML, this could be done in a myriad of ways - this is only one solution.
Hope this helps!
I know this is very old, but I thought I would attempt to do what the OP asked. And as such this is my attempt. BTW, before I continue, I should point out that for some reason, the OPs measurements didn't quite work out when using DLUs, but I think I've come reasonably close. Also please keep in mind I'm still a relative n00b when it comes to this stuff... so if I've done something wrong or blasphemous... apologies.
First I had to find a way to get the width and height of a given letter of a given font (In my case, Segoe UI at 10px)... which for that I used this SO answer: how-to-calculate-wpf-textblock-width-for-its-known-font-size-and-characters to which I made a static class to hold the resulting doubles:
public static class Fonts
{
public static double HorizontalDluMultiplier;
public static double VerticalDluMultiplier;
static Fonts()
{
var formattedText = new FormattedText(
"A",
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface("Segoe UI"),
12.0,
Brushes.Black);
Fonts.HorizontalDluMultiplier = formattedText.Width / 4;
Fonts.VerticalDluMultiplier = formattedText.Height / 8;
}
}
Once I had the metrics I had to create a WPF converter that takes a given ConverterParameter (In this case a number in DLUs) and spits out a double of pixels. This is the converter I used...
public class HorizontalDluToPixelConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (Double.Parse((parameter as string))) * Fonts.HorizontalDluMultiplier;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think it goes without saying that I had a seperate Vertical version of the converter.
Once that was done, I was just a matter of laying out the window in XAML and when it came to setting heights and widths, using the converter. I used a single grid to lay out the entire window. but to set the column widths and row heights I used the converter like so:
<Window.Resources>
<converters:HorizontalDluToPixelConverter x:Key="HorizontalConverter" />
<converters:VerticalDluToPixelConverter x:Key="VerticalConverter" />
</Window.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding Converter={StaticResource VerticalConverter}, ConverterParameter=7}" />
etc...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Converter={StaticResource HorizontalConverter}, ConverterParameter=7}" />
etc... etc...
</Grid.ColumnDefinitions>
Hope this helps future people as well (if it is infact helpful heh)
Look into the Grid control - it has support for relative sizing.
Here is a more detailed link I found on MSDN about Layout Metrics. WPF DIUs are defined as 1/96 of an inch and DLU to pixel conversions are font dependent as you can see in the table shown below.
So using this information along with a systems DPI setting and depending on the font that you are targeting you could figure out how many DUI correlate to a given measurement in vertical or horizontal DLU units. I haven't seen any javascript based calculators for this yet but it would be pretty trivial to create a similar tool in any programming language that makes this a little easier.
The Canvas layout element allows for coordinate-based layout similar to what you're used to and if you have a Canvas you even get some guidelines in the visual editor. eg:
<Window xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:d='http://schemas.microsoft.com/expression/blend/2008' mc:Ignorable='d' Title='Spin-Echo Image Processing' Width='673' x:Class='ImageR2.CLASPmap' Height='961' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
<Canvas Name='canvas1'>
<TextBlock Name='TEXT_Program' Canvas.Top='27' Width='133' Height='21' Canvas.Left='875'>CLASPmap:</TextBlock>
<TextBlock Name='TEXT_Heading' Canvas.Top='27' Width='368' Height='27' Canvas.Left='1008'>Transverse Relaxation Rate Mapping</TextBlock>
<TextBlock Name='TEXT_XYCoordinates' Canvas.Top='251' Width='139' Height='21' Canvas.Left='869'>X & Y Coordinates</TextBlock>