WPF: Как указать единицы в диалоговых модулях?

Я пытаюсь выяснить, как разложить простой диалог в WPF, используя соответствующие диалоговые модули (DLU).


Что такое диалоговое окно?

Диалог - это единица измерения, основанная на предпочтительном размере шрифта пользователя. Диалоговое окно определено так, что средний символ - 4 диалога единиц на 8 диалоговом уровне:

enter image description here

Это означает, что диалоговые блоки:

  • изменить выбранный шрифт
  • изменено с выбранной настройкой DPI
  • не являются квадратными

я потратил около двух часов на определение этого диалогового окна образца из Windows Vista с различными измерениями dlu. Может ли кто-нибудь указать соответствующую разметку XAML, которая генерирует это диалоговое окно?

alt text http://i44.tinypic.com/30a7390.jpg (Ссылка на изображение)

Теперь, по общему признанию, я почти ничего не знаю о WPF XAML. Каждый раз, когда я начинаю, я становлюсь заглушенным, потому что я не могу понять, как разместить любой элемент управления. Кажется, что все в WPF должно содержаться на какой-то панели. Там StackPanels, FlowPanels, DockPanel, Grid и т.д. Если у вас нет одного из них, он не будет компилироваться.

Единственный XAML, с которым я смог придумать (uing 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?

Примечание.. Вы не можете измерить скриншот. Все значения ширины и высоты диалогового окна (dlu) указаны.

Примечание: 1 горизонтальный DLU!= 1 вертикальный DLU. Горизонтальные и вертикальные DLU имеют разные размеры.


См. также

Bump: 6/20/2011

Ответ 1

Следующий XAML даст вам эффект, который вы ищете.

Обратите внимание, что я удвоил единицы DLU в разметке - таким образом, сохраняя один и тот же аспект. Это выглядело забавно, когда у Button была высота 14 единиц. Возможно, вам придется переделывать цифры, представленные на рынке.

Кроме того, я начал удалять некоторые "макеты Vista" в отдельные стили. Возможно, вы сможете продолжить этот путь, так что у вас есть многократно используемый набор стилей, которые следуют рекомендациям 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, это может быть сделано множеством способов - это только одно решение.

Надеюсь, это поможет!

Ответ 2

Я знаю, что это очень старый, но я думал, что попытаюсь сделать то, что задал ОП. И как таковая это моя попытка. Кстати, прежде чем я продолжу, я должен указать, что по некоторым причинам измерения OPs не совсем работали при использовании DLU, но я думаю, что я подошел достаточно близко. Также, пожалуйста, имейте в виду, что я все еще относительный n00b, когда дело доходит до этого материала... так что если я сделал что-то неправильно или богохульно... извинения.

Final Result

Сначала мне пришлось найти способ получить ширину и высоту заданной буквы данного шрифта (в моем случае, Segoe UI в 10px)... для чего я использовал этот SO ответ: how-to-calculate-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-конвертер, который принимает данный конвертер (в этом случае число в 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>

Надеюсь, что это тоже поможет будущим людям (если это полезно, хе-хе)

Ответ 3

Посмотрите Grid control - он поддерживает относительный размер.

Ответ 4

Вот более подробная ссылка, которую я нашел в MSDN о Макетные показатели. WPF DIU определяются как 1/96 дюйма, а конверсии DLU в пиксели зависят от шрифта, как вы можете видеть в таблице, показанной ниже.

Converting from DLUs to relative pixels and back

Таким образом, используя эту информацию вместе с настройкой DPI системы и в зависимости от шрифта, на который вы нацеливаете, вы можете выяснить, сколько DUI коррелирует с данным измерением в вертикальных или горизонтальных блоках DLU. Я пока не видел никаких калькуляторов на основе javascript, но было бы довольно тривиально создавать подобный инструмент на любом языке программирования, что упростит это.

Ответ 5

Элемент макета Canvas позволяет использовать макет на основе координат, аналогичный тому, к которому вы привыкли, и если у вас есть Canvas, вы даже получаете некоторые рекомендации в визуальном редакторе. например:

<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 &amp; Y Coordinates</TextBlock>