WPF: Как указать единицы в диалоговых единицах? - PullRequest
25 голосов
/ 27 декабря 2008

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


Что такое диалоговое устройство?

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

enter image description here

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

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

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

alt text ( Ссылка на изображение )

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

Единственный 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?

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

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


Смотри также

Bump: 6/20/2011

Ответы [ 5 ]

7 голосов
/ 28 декабря 2008

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

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

Кроме того, я начал убирать некоторые из «Макетов Vista» в отдельные стили. Возможно, вы сможете продолжить этот путь, чтобы у вас был достаточно многократно используемый набор стилей, которые следуют рекомендациям Vista. Я вполне уверен, что некоторые другие люди сделали что-то подобное.

Кроме того, я взял на себя смелость с размером диалога. Вы упомянули, что хотели 210x96 единиц - вам нужно установить эту сумму, а также окно Chrome.

В любом случае, с содержанием:

  <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 голосов
/ 04 октября 2014

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

Final Result

Сначала я должен был найти способ получить ширину и высоту данной буквы данного шрифта (в моем случае, Segoe UI на 10px) ... для чего я использовал этот SO-ответ: как -to-вычисления-wpf-textblock-ширина-для-его-известных-размера-шрифта-и-символов , к которым я сделал статический класс для хранения результирующих значений типа double:

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>

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

1 голос
/ 22 мая 2010

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

Converting from DLUs to relative pixels and back

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

1 голос
/ 27 декабря 2008

Просмотрите элемент управления Grid - в нем есть поддержка относительного размера.

0 голосов
/ 27 мая 2009

Элемент макета 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>
...