窗口模板中的边框边距与WindowChrome一起使用时没有任何效果

hat*_*enn 12 c# wpf xaml windows-shell window-chrome

我正在图书馆检查WindowChrome课程System.Windows.Shell(v 3.5.41019.1).当我尝试创建Window模板时,模板中Border元素的边距似乎没有效果:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
        Title="MainWindow" Height="350" Width="525" Style="{DynamicResource WindowStyle1}">
    <Window.Resources>
        <Style x:Key="WindowStyle1" TargetType="{x:Type Window}">
<!-- Here is the WindowChrome.-->
            <Setter Property="shell:WindowChrome.WindowChrome">
                <Setter.Value>
                    <shell:WindowChrome />
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Window}">
<!-- And here is the Border. Its margin has no effect as far as I can tell.-->
                        <Border Margin="25" Background="Red">
                            <AdornerDecorator>
                                <ContentPresenter/>
                            </AdornerDecorator>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>

    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

您认为原因是什么?我想知道,因为我看到有些人使用像*这样的东西:

<Border x:Name="WindowBorder" Margin="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowNonClientFrameThickness}" Background="Red">
Run Code Online (Sandbox Code Playgroud)

但由于它在我的测试中没有任何影响,这样做有什么意义呢?

(*)其中一个使用的地方是CodePlex上的ModernUI项目.

编辑:我已在Windows 7上使用Aero对此进行了测试.

编辑2: Aero关闭时仍然如此.

ter*_*rry 8

根据MSDN,WindowChrome

表示描述窗口的非客户区域的自定义的对象.

在阅读MSDN示例并播放您的代码一段时间后,我注意到您的代码应该类似于以下MSDN示例代码:

<Style x:Key="StandardStyle" TargetType="{x:Type local:MainWindow}">
<Setter Property="shell:WindowChrome.WindowChrome">
    <Setter.Value>
        <shell:WindowChrome />
    </Setter.Value>
</Setter>
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:MainWindow}">
            <!--Note there is a Grid as the root-->
            <Grid>
                <Border Background="White"
                        Margin="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowNonClientFrameThickness}">
                    <ContentPresenter Content="{TemplateBinding Content}" />
                </Border>
                <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" 
                           VerticalAlignment="Top" HorizontalAlignment="Left" 
                           Margin="36,8,0,0"/>
                <Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}"
                       VerticalAlignment="Top" HorizontalAlignment="Left"
                       Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(shell:WindowChrome.WindowChrome).ResizeBorderThickness}" 
                       Width="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=SmallIconSize.Width}"
                       shell:WindowChrome.IsHitTestVisibleInChrome="True"/>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>
Run Code Online (Sandbox Code Playgroud)

注意,有一个Grid作为根元素,它包含一些用于自定义窗口NC的元素.

更新:

您可能会注意到在MSDN页面的注释中,它包含以下部分:

WindowStyle.None

WindowChrome

这是自定义WPF应用程序窗口外观的两种方法.

但是,将Window.WindowStyle属性设置为WindowStyle.None:

这将从窗口中删除非客户端框架,并仅保留客户端区域,您可以应用自定义样式.但是,当删除非客户端框架时,您还会丢失它提供的系统功能和行为,例如标题按钮和窗口大小调整.另一个副作用是窗口将在最大化时覆盖Windows任务栏.

然后WindowChrome介绍使用WPF启用NC自定义:

要在保留其标准功能的同时自定义窗口,可以使用WindowChrome类.WindowChrome类将窗口框架的功能与视觉效果分开,并允许您控制应用程序窗口的客户端和非客户端区域之间的边界.WindowChrome类允许您通过扩展客户区覆盖非客户区来将WPF内容放在窗口框架中.同时,它通过两个不可见的区域保留系统行为; 调整边框和标题区域.

回到你的问题,你找到的模板应该从MSDN示例代码中复制,但是错过了真正的根Grid.边界边缘是为NC提供一些空间.在MSDN示例代码中,ContenPreseter仅包含客户端区域,而NC包含Border,一个TextBlock用于窗口标题,和Image用于窗口的图标.

回顾一下,通过设置,WindowChrome您可以自定义窗口的NC区域Window.Template.

注意: 示例MSDN示例代码在.Net 4.5中似乎有点过时,System.Windows.Shell.WindowChrome现在位于PresentationFramework.dll,所以代码可能如下所示:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" Style="{DynamicResource WindowStyle1}" Icon="Icon1.ico">
<Window.Resources>
    <Style x:Key="WindowStyle1" TargetType="{x:Type Window}">
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome />
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Grid>
                        <Border Background="Red"
                        Margin="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}}">
                            <ContentPresenter Content="{TemplateBinding Content}" />
                        </Border>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" 
                           VerticalAlignment="Top" HorizontalAlignment="Left" 
                           Margin="36,8,0,0"/>
                        <Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon}"
                       VerticalAlignment="Top" HorizontalAlignment="Left"
                       Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=WindowChrome.WindowChrome.ResizeBorderThickness}" 
                       Width="{Binding Source={x:Static SystemParameters.SmallIconWidth}}"
                       WindowChrome.IsHitTestVisibleInChrome="True"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<Grid>
    <Button />
</Grid>
Run Code Online (Sandbox Code Playgroud)