Я пытаюсь понять, как разметить простой диалог в WPF, используя правильный блоки диалога (DLU).
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
Я потратил около двух часов на определение размеров этого образца диалогового окна в Windows Vista с различными измерениями dlu. Может ли кто-нибудь дать соответствующую разметку XAML, которая генерирует это диалоговое окно?
Теперь по общему признанию я почти ничего не знаю о WPF XAML. Каждый раз, когда я начинаю, я захожу в тупик, потому что не могу понять, как установить какой-либо контроль. Кажется, что все в WPF должно содержаться на какой-то панели. Есть StackPanels, FlowPanels, DockPanel, Сетка и т. д. Если у вас нет одного из них, он не будет компилироваться.
Единственный XAML, который мне удалось придумать (используя XAMLPad):
<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>
Что представляет собой безвкусное чудовище. Ни один из элементов управления не размещен и не имеет правильного размера. Я не могу понять, как позиционировать элементы управления в окне и как правильно их определять.
Может ли кто-нибудь превратить этот снимок экрана в XAML?
Примечание: Вы не можете измерять скриншот. Указаны все значения ширины и высоты Dialog Unit (dlu).
Примечание: 1 горизонтальный DLU! = 1 вертикальный DLU. Горизонтальные и вертикальные DLU бывают разных размеров.
Ударяться: 20.06.2011





Посмотрите на Сетка управления - он поддерживает относительный размер.
Следующий XAML даст вам желаемый эффект.
Обратите внимание, что я удвоил единицы DLU в разметке - таким образом, сохранил тот же аспект. Это выглядело забавно, имея высоту кнопки в 14 единиц. Возможно, вам придется повозиться с цифрами, представленными на рынке.
Кроме того, я начал выделять некоторые из «Vista Layout» в отдельные стили. Возможно, вы сможете продолжить этот путь, чтобы получить достаточно многоразовый набор стилей, соответствующих рекомендациям Vista. Я почти уверен, что некоторые другие люди сделали нечто подобное.
Кроме того, я позволил себе некоторые вольности с размером диалогового окна. Вы упомянули, что хотите 210x96 единиц - вам нужно будет установить это количество плюс хром окна.
Во всяком случае, по содержанию:
<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>
Как и в случае с большинством XAML, это можно сделать множеством способов - это только одно решение.
Надеюсь это поможет!
Откуда вы берете значения ширины и высоты? Будут ли эти числа масштабироваться в соответствии с предпочтениями пользователя шрифта Windows? Насколько я понимаю, любые длины, указанные без единиц измерения, считаются «логическими пикселями», где 1 логический пиксель равен 1/96 дюйма.
XamlPad не может показать вам элементы <Window>, т.е. будет подавляться вещами <Window> из-за некоторой безопасности. Так что я все равно не могу его просмотреть.
Вы разрабатываете приложение Xdap? Если это так, вам нужно будет изменить Window на userControl. Этот класс предполагает наличие файла с выделенным кодом. Попробуйте создать новый UserControl и скопировать XAML. Замените Window на UserControl. Конечно, вам придется обновить имя x: Class.
Окно будет масштабироваться в соответствии с предпочтениями пользователя в DPI, но не обязательно с их предпочтениями шрифта. Этот xaml не учитывает выбор шрифта пользователем - он использует Segeo UI, который я считаю стандартным (хотя я могу ошибаться).
Я провел небольшое исследование DLU, которое, похоже, основано на размере шрифта. Система компоновки WPF основана на устройствах, не зависящих от устройства. Я не знаю, как использовать DLU в WPF. Тем не менее, представленный макет должен стать хорошей отправной точкой для создания диалогового окна разумного размера.
Элемент макета холста позволяет создавать макет на основе координат, аналогичный тому, к которому вы привыкли, и если у вас есть холст, вы даже получите некоторые рекомендации в визуальном редакторе. например:
<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>
Проблема в том, что вводимые вами значения принимаются WPF как пиксели. Где снимок экрана предоставляет значения в горизонтальных и вертикальных диалоговых единицах (DLU). И чтобы уточнить, DLU не обязательно квадратные.
Вот более подробная ссылка, которую я нашел в MSDN о Показатели макета. WPF DIU определены как 1/96 дюйма, а преобразования DLU в пиксели зависят от шрифта, как вы можете видеть в таблице, показанной ниже.
![]()
Таким образом, используя эту информацию вместе с настройкой DPI системы и в зависимости от шрифта, на который вы ориентируетесь, вы можете выяснить, сколько DUI коррелирует с данным измерением в вертикальных или горизонтальных единицах DLU. Я еще не видел для этого никаких калькуляторов на основе javascript, но было бы довольно тривиально создать аналогичный инструмент на любом языке программирования, который сделает это немного проще.
я не думаю, что это тривиально; никто еще не смог этого сделать.
Я знаю, что это очень старый, но я подумал, что попытаюсь сделать то, что попросил OP. И это моя попытка. Кстати, прежде чем продолжить, я должен указать, что по какой-то причине измерения OP не совсем сработали при использовании DLU, но я думаю, что я подошел достаточно близко. Также, пожалуйста, имейте в виду, что я все еще относительный новичок, когда дело доходит до этого ... так что если я сделал что-то не так или кощунственно ... извиняюсь.

Сначала мне нужно было найти способ получить ширину и высоту заданной буквы данного шрифта (в моем случае, пользовательский интерфейс Segoe с размером 10 пикселей) ... для чего я использовал этот ответ SO: как-вычислить-wpf-textblock-width-for-its-known-font-size-and-characters, для которого я сделал статический класс для хранения результирующих двойников:
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;
}
}
Когда у меня были метрики, мне пришлось создать конвертер WPF, который принимает заданный параметр ConverterParameter (в данном случае число в DLU) и выдает двойные пиксели. Это конвертер, который я использовал ...
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();
}
}
Думаю, само собой разумеется, что у меня была отдельная Вертикальная версия конвертера.
Как только это было сделано, мне оставалось только разместить окно в XAML, а когда дело дошло до установки высоты и ширины, с помощью конвертера. Я использовал единую сетку, чтобы выложить все окно. но чтобы установить ширину столбцов и высоту строк, я использовал конвертер следующим образом:
<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>
Надеюсь, это поможет и будущим людям (если это действительно полезно, хех)
Принимает ли система управления сетью такие устройства, как:
width = "210dlu"в дополнение кwidth = "9999px"?