WPF:如何在对话框单位中指定单位?

发布于 2024-07-11 01:16:37 字数 3137 浏览 9 评论 0原文

我试图弄清楚如何使用正确的对话框单元 (DLU) 在 WPF 中布局一个简单的对话框。


什么是对话单元?

<小时>

对话框是一种基于用户首选字体大小的度量单位。 对话单元的定义使得平均字符为 4 个对话 宽单位乘以 8 个对话单位高:

在此处输入图像描述

这意味着对话框单元:

  • 更改所选字体
  • 随选定的 DPI 设置而更改
  • 不是正方形

我花了大约两个小时使用各种 dlu 测量值从 Windows Vista 中调整此示例对话框的尺寸。 有人可以提供生成此对话框的相应 XAML 标记吗?

替代文本

(图像链接)

现在不可否认,我对 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 的尺寸不同。


另请参阅

凹凸: 2011年6月20日

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:

enter image description here

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

(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

Bump: 6/20/2011

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

蓝梦月影 2024-07-18 01:16:37

下面的 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 一样,这可以通过多种方式完成 - 这只是一种解决方案。

希望这可以帮助!

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!

厌味 2024-07-18 01:16:37

我知道这已经很老了,但我想我会尝试做OP要求的事情。 因此,这就是我的尝试。 顺便说一句,在继续之前,我应该指出,由于某种原因,使用 DLU 时 OP 测量结果不太好,但我认为我已经相当接近了。 另外请记住,当涉及到这些东西时,我仍然是一个相对的n00b......所以如果我做错了什么或亵渎神明......道歉。

Final Result

首先,我必须找到一种方法来获取给定字体的给定字母的宽度和高度(在我的案例,Segoe UI 为 10px)...为此我使用了这个答案: 如何计算我制作的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>

希望这也能帮助未来的人(如果它实际上有帮助的话)

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.

Final Result

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)

平生欢 2024-07-18 01:16:37

查看 网格控件 - 它有支持相对大小。

Look into the Grid control - it has support for relative sizing.

奶气 2024-07-18 01:16:37

以下是我在 MSDN 上找到的有关 布局指标 的更详细链接。 WPF DIU 定义为 1/96 英寸,DLU 到像素的转换取决于字体,如下表所示。

从 DLU 转换为相对像素并返回

因此,使用此信息以及系统 DPI 设置,并根据您的目标字体,您可以计算出有多少 DUI 与垂直或水平 DLU 单位的给定测量值相关。 我还没有看到任何基于 javascript 的计算器,但是用任何编程语言创建一个类似的工具来使这变得更容易一点是非常简单的。

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.

Converting from DLUs to relative pixels and back

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.

陌生 2024-07-18 01:16:37

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

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文