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

24

我正在尝试使用适当的对话框单位 (DLUs) 布局 WPF 中的简单对话框。


什么是对话框单元?

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

enter image description here

这意味着对话框单元:

  • 随所选字体而变化
  • 随所选DPI设置而变化
  • 不是正方形

我花了约两个小时用各种dlu测量标准规划了这个Windows Vista示例对话框。请问有人可以提供相应的XAML标记以生成此对话框吗? alt textImage Link
现在承认,我对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大小不同。


参见

顶起: 6/20/2011

5个回答

8
以下的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英寸。 - Ian Boyd
XamlPad无法显示<Window>的内容,而ie会因某些安全原因而无法处理<Window>的内容。所以无论如何我都无法查看它。 - Ian Boyd
你正在开发一个 Xdap 应用程序吗?如果是这样的话,你需要将 Window 更改为 userControl。该类假定存在一个代码后台文件。尝试创建一个新的 UserControl,并复制 XAML。用 UserControl 替换 Window。当然,你还需要更新 x:Class 名称。 - Brad Leach
2
窗口大小将根据用户的 DPI 偏好进行缩放,但不一定会根据用户的字体偏好进行缩放。这个 XAML 没有考虑到用户的字体选择 - 它使用 Segeo UI 作为标准(尽管我可能错了)。 - Brad Leach
2
我对DLUs进行了一些调查 - 它们似乎是基于字体大小的。WPF的布局系统是基于设备无关单位的。我不知道在WPF中使用DLUs的方法。话虽如此,所呈现的布局应该为您创建一个合理大小的对话框提供了一个良好的起点。 - Brad Leach

2
我知道这很古老,但我想尝试做一下OP要求的事情。因此这是我的尝试。顺便说一下,在我继续之前,我应该指出,由于某种原因,当使用DLUs时,OP的测量结果并不完全正确,但我认为我已经接近了。还请记住,对于这些东西我仍然是一个相对的n00b...所以如果我做错或亵渎了什么...请原谅。
首先,我必须找到一种方法来获取给定字体(在我的例子中为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转换器,它可以接受给定的ConverterParameter(在这种情况下是DLUs中的数字),并输出像素值的double类型。这是我使用的转换器...

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

我在MSDN上找到了一个更详细的链接,关于布局度量。WPF DIU被定义为1/96英寸,DLU到像素的转换取决于字体,如下表所示。

Converting from DLUs to relative pixels and back

因此,结合系统的 DPI 设置以及您所针对的字体,您可以确定多少个 DUI 对应于垂直或水平 DLU 单位中的给定测量值。我还没有看到任何基于 JavaScript 的计算器,但在任何编程语言中创建类似工具都将非常简单。


1
我认为这并不是微不足道的事情;迄今为止还没有人能够做到它。 - Ian Boyd

1

2
网格控件是否接受像 width="210dlu" 这样的单位,除了 width="9999px" 之外? - Ian Boyd

0

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>

1
问题在于您输入的值被WPF假定为像素。而截图提供的是水平和垂直对话框单位(DLUs)的值。需要澄清的是,DLUs不一定是正方形的。 - Ian Boyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接