2013-05-17 62 views
11

我正在檢出System.Windows.Shell庫(v 3.5.41019.1)中的WindowChrome類。當我嘗試創建一個Window模板,在模板中Border元素的邊距,似乎沒有任何效果:與WindowChrome一起使用時,Window模板中的邊框邊距沒有任何影響

<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> 

你覺得是什麼原因呢?我想知道的是,因爲我看到一些人使用類似*:

<Border x:Name="WindowBorder" Margin="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowNonClientFrameThickness}" Background="Red"> 

但由於它沒有在我的測試中沒有任何影響,這可能是這樣做的呢?

(*)其中一個地方是ModernUI項目CodePlex

編輯:我已經用Aero在Windows 7上測試過了。

編輯2:它仍然與Aero關閉相同。

回答

7

根據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> 

注意,有一個網格根元素其中包含一些用於自定義窗口NC的元素。

UPDATE:

您可以在MSDN頁面的備註注意到,它包含幾個部分:

WindowStyle.None

WindowChrome

這些自定義外觀的兩種方式的WPF應用程序窗口。

然而,Window.WindowStyle屬性設置爲WindowStyle.None

這消除了從窗口非客戶端框架,只保留了 客戶區,您可以將自定義樣式。但是,如果刪除了非客戶端幀,則還會丟失其提供的系統功能和 行爲,例如字幕按鈕和窗口大小調整。另一個副作用是該窗口將在最大化時覆蓋Windows任務欄的 。

然後WindowChrome介紹了使用WPF,使NC定製:

要自定義窗口,同時保留其標準功能,您 可以使用WindowChrome類。 WindowChrome類將窗口框架的 功能與視覺效果分開,並讓您控制 應用程序窗口的客戶端和非客戶端區域之間的邊界。 WindowChrome類允許您通過擴展客戶區來覆蓋非客戶端 區域,將WPF內容放置在窗口框架的 中。同時,它通過兩個不可見的區域保留系統行爲;調整邊框和標題區域。

所以回到你的問題,你找到了模板,應該從MSDN示例代碼複製,但錯過了真正的根Grid。 邊界上的邊緣是爲了給NC提供一些空間。 在MSDN示例代碼中,ContenPreseter僅包含客戶端區域,而NC包含窗口圖標的BorderTextBlock和窗口圖標的Image

回顧一下,設置WindowChrome使您可以在Window.Template中自定義窗口的NC區域。

注: 樣本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> 

+0

你是對的我相信。他們從MSDN複製了代碼,並以某種方式保持這種狀態。 – hattenn

1

我認爲你試圖設置邊框的方式存在一些誤解。這裏是WindowChrome類的解釋爲msdn

提供的WindowChrome類分開的視覺效果窗框的功能,並允許您控制您的應用程序窗口的客戶和非客戶端區域之間的邊界。 WindowChrome類允許您通過擴展客戶區以覆蓋非客戶區來將WPF內容放入窗口框架中。同時,它通過兩個無形的領域保留了系統行爲;調整邊框和標題區域。

因此,如果您嘗試自定義窗口的NonClient區域,那麼它不是內容展示器,您應該將Border設置爲。這是客戶區。相反,在模板中,您可以添加除Content Presenter之外的XAML以定義您的NonClient區域。我只是根據您的代碼嘗試了一個簡單的代碼,它將窗口的標題屬性向右移動了值100.這是代碼。

<Window x:Class="WPF_ToggleButton.ShellWindow" 
    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}"> 
     <Setter Property="shell:WindowChrome.WindowChrome"> 
      <Setter.Value> 
       <shell:WindowChrome /> 
      </Setter.Value> 
     </Setter> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Window}"> 
        <Grid> 
         <Border Background="Yellow"> 
          <AdornerDecorator> 
           <ContentPresenter Content="{TemplateBinding Content}"/> 
          </AdornerDecorator> 
         </Border> 
         <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" 
          VerticalAlignment="Top" HorizontalAlignment="Left" 
          Margin="100,0,0,0"/> 
        </Grid>       
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 
<Grid> 
    <Border Margin="50" Background="AliceBlue"/> 
</Grid> 

因此,你可以在使用XAML代碼,如圖片代表您的窗口關閉按鈕,等在非工作區的任何元素。在窗口中的最後一個元素定義了傳遞的內容呈現在模板

總之,如果你wan't定製客戶區使用內容呈現在客戶區域,而如果你有興趣在改變非客戶區如標題欄顯示,關閉圖像圖標,然後在模板中定義它。

一個簡短的觀察。我認爲保證金對於Window而言沒有任何意義。嘗試設置它爲一個正常的窗口,我認爲它不會尊重它。

+0

首先,對於評論遲到道歉。過去幾天我一直很忙。我知道如何使用'WindowChrome'。問題是,當你使用'WindowChrome'並定義一個模板時,'ControlTemplate'中第一個'Layout'元素的'Margin'屬性沒有任何作用。你的代碼有完全相同的東西。試着把'Margin'放到你的Grid中(ControlTemplate中的第一個),它沒有任何作用。如果你刪除'WindowChrome',你可以看到'Margin'在普通的'Window'上被黑色填充。 – hattenn

+0

事情是,我正在看'ModernUI',看到他們在'Window'的'ControlTemplate'的第一個'Layout'元素周圍放了一個'Margin'(然後我在一些東西中看到了同樣的東西其他地方,我猜他們都是從同一個地方複製粘貼的。)但是這對我沒有任何改變。我想知道,因爲也許有些東西我不知道,也許它適用於Windows XP或Windows 8.我只是想澄清一下。 – hattenn

+0

我並不完全理解你的評論,我很抱歉。您不想在控制模板中爲網格設置邊距。該保證金將相對於哪個元素?例如,我的意思是,從哪個元素的邊距100? – Jatin