Comment puis-je créer une fenêtre personnalisée de base chrome pour une fenêtre WPF, qui n'inclut pas le bouton de fermeture et toujours une fenêtre mobile et redimensionnable?
Vous définissez le WindowStyle="None"
, puis créez votre propre interface de fenêtre. Vous devez créer vos propres gestionnaires d'événements Min/Max/Close/Drag, mais le redimensionnement est toujours maintenu.
Par exemple:
<Window
WindowState="Maximized"
WindowStyle="None"
WindowStartupLocation="CenterScreen"
MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"
>
<DockPanel x:Name="RootWindow">
<DockPanel x:Name="TitleBar" DockPanel.Dock="Top">
<Button x:Name="CloseButton" Content="X"
Click="CloseButton_Click"
DockPanel.Dock="Right" />
<Button x:Name="MaxButton" Content="Restore"
Click="MaximizeButton_Click"
DockPanel.Dock="Right" />
<Button x:Name="MinButton" Content="Min"
Click="MinimizeButton_Click"
DockPanel.Dock="Right" />
<TextBlock HorizontalAlignment="Center">Application Name</TextBlock>
</DockPanel>
<ContentControl Content="{Binding CurrentPage}" />
</DockPanel>
</Window>
Et voici quelques exemples de code-derrière pour la fonctionnalité de fenêtre commune
/// <summary>
/// TitleBar_MouseDown - Drag if single-click, resize if double-click
/// </summary>
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton == MouseButton.Left)
if (e.ClickCount == 2)
{
AdjustWindowSize();
}
else
{
Application.Current.MainWindow.DragMove();
}
}
/// <summary>
/// CloseButton_Clicked
/// </summary>
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
/// <summary>
/// MaximizedButton_Clicked
/// </summary>
private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
AdjustWindowSize();
}
/// <summary>
/// Minimized Button_Clicked
/// </summary>
private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
/// <summary>
/// Adjusts the WindowSize to correct parameters when Maximize button is clicked
/// </summary>
private void AdjustWindowSize()
{
if (this.WindowState == WindowState.Maximized)
{
this.WindowState = WindowState.Normal;
MaximizeButton.Content = "1";
}
else
{
this.WindowState = WindowState.Maximized;
MaximizeButton.Content = "2";
}
}
. NET 4.5 a ajouté une nouvelle classe qui simplifie grandement cela.
classe WindowChrome vous permet d'étendre le contenu Windows Presentation Foundation (WPF) dans la zone non cliente d'une fenêtre qui est généralement réservé au gestionnaire de fenêtres du système d'exploitation.
Vous pouvez trouver un tutoriel ici .
Et voici un court exemple d'utilisation .
Je viens d'utiliser l'exemple ci-dessous pour .net 4.5 et cela fonctionne très bien. Fait intéressant, il utilise un code derrière pour un dictionnaire de ressources pour les événements de clic. Il vous suffit de référencer le dictionnaire de ressources dans votre app.xaml
fichier, puis attribuez à la fenêtre le style CustomWindowStyle
. Cela a été volé sans vergogne à http://www.eidias.com/blog/2014/1/27/restyle-your-window .
<ResourceDictionary x:Class="WpfApp7.WindowStyle"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
<Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="30"
CornerRadius="4"
GlassFrameThickness="0"
NonClientFrameEdges="None"
ResizeBorderThickness="5"
UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Background" Value="Gray" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="5,30,5,5">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
<Grid Height="30"
VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Margin="5,0">
<Button Content="A" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
<Button Content="B" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
<Button Content="C" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
<Button Content="D" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
</StackPanel>
<TextBlock Margin="5,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{TemplateBinding Title}"
Grid.Column="1"/>
<StackPanel Orientation="Horizontal"
Grid.Column="2">
<Button x:Name="btnClose"
Width="15"
Margin="5"
Click="CloseClick"
Content="X"
WindowChrome.IsHitTestVisibleInChrome="True" />
<Button x:Name="btnRestore"
Width="15"
Margin="5"
Click="MaximizeRestoreClick"
Content="#"
WindowChrome.IsHitTestVisibleInChrome="True" />
<Button x:Name="btnMinimize"
Width="15"
Margin="5"
VerticalContentAlignment="Bottom"
Click="MinimizeClick"
Content="_"
WindowChrome.IsHitTestVisibleInChrome="True" />
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Et pour le code derrière:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp7
{
public partial class WindowStyle : ResourceDictionary
{
public WindowStyle()
{
InitializeComponent();
}
private void CloseClick(object sender, RoutedEventArgs e)
{
var window = (Window)((FrameworkElement)sender).TemplatedParent;
window.Close();
}
private void MaximizeRestoreClick(object sender, RoutedEventArgs e)
{
var window = (Window)((FrameworkElement)sender).TemplatedParent;
if (window.WindowState == System.Windows.WindowState.Normal)
{
window.WindowState = System.Windows.WindowState.Maximized;
}
else
{
window.WindowState = System.Windows.WindowState.Normal;
}
}
private void MinimizeClick(object sender, RoutedEventArgs e)
{
var window = (Window)((FrameworkElement)sender).TemplatedParent;
window.WindowState = System.Windows.WindowState.Minimized;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello!");
}
}
}
Voici une solution simple qui ressemble beaucoup aux boutons par défaut de Windows 10, elle utilise simplement la même police pour les symboles:
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True">
<Button Click="Minimize_Click" Content="" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,15,15,5" Background="Transparent" BorderBrush="Transparent" />
<Button Click="Maximize_Click" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Button.Content" Value="" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximized">
<Setter Property="Button.Content" Value="" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Click="Close_Click" Content="" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent" />
</StackPanel>
Si vous souhaitez prendre en charge les anciennes versions de Windows (7 et 8), consultez ici: https://stackoverflow.com/a/27911618/9758687