WPF自定义Window样式(1)

时间:2022-05-12 09:13:18

目录:

WPF自定义Window样式(1)

WPF自定义Window样式(2)

1. 引言

WPF是制作界面的一大利器。最近在做一个项目,用的就是WPF。既然使用了WPF了,那么理所当然的,需要自定义窗体样式。所使用的代码是在网上查到的:原文链接

首先上原始源码

2. 创建项目

创建空白项目stonemqy.CustomWindow,添加WPF项目stonemqy.CustomWindow.Main。在stonemqy.CustomWindow.Main中添加文件夹Themes,并在其中添加资源字典Generic.xaml,注意这里的Themes文件夹和Generic.xaml资源字典的名字不可更改。并在项目下依次添加类VisualStates、TransitioningContentControl和CustomWindow。

3. VisualStates

using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Media; namespace stonemqy.CustomWindow.Main
{
public static class VisualStates
{ /// <summary>
/// This method tries to get the named VisualStateGroup for the
/// dependency object. The provided object's ImplementationRoot will be
/// looked up in this call.
/// </summary>
/// <param name="dependencyObject">The dependency object.</param>
/// <param name="groupName">The visual state group's name.</param>
/// <returns>Returns null or the VisualStateGroup object.</returns>
public static VisualStateGroup TryGetVisualStateGroup(DependencyObject dependencyObject, string groupName)
{
FrameworkElement root = GetImplementationRoot(dependencyObject);
if (root == null)
{
return null;
} return VisualStateManager.GetVisualStateGroups(root)
.OfType<VisualStateGroup>()
.Where(group => string.CompareOrdinal(groupName, group.Name) == )
.FirstOrDefault();
} /// <summary>
/// Gets the implementation root of the Control.
/// </summary>
/// <param name="dependencyObject">The DependencyObject.</param>
/// <remarks>
/// Implements Silverlight's corresponding internal property on Control.
/// </remarks>
/// <returns>Returns the implementation root or null.</returns>
public static FrameworkElement GetImplementationRoot(DependencyObject dependencyObject)
{
Debug.Assert(dependencyObject != null, "DependencyObject should not be null.");
return ( == VisualTreeHelper.GetChildrenCount(dependencyObject)) ?
VisualTreeHelper.GetChild(dependencyObject, ) as FrameworkElement :
null;
}
}
}

4. TransitioningContentControl

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation; namespace stonemqy.CustomWindow.Main
{
/// <summary>
/// Represents a control with a single piece of content and when that content
/// changes performs a transition animation.
/// </summary>
/// <QualityBand>Experimental</QualityBand>
/// <remarks>The API for this control will change considerably in the future.</remarks>
[TemplateVisualState(GroupName = PresentationGroup, Name = NormalState)]
[TemplateVisualState(GroupName = PresentationGroup, Name = DefaultTransitionState)]
[TemplatePart(Name = PreviousContentPresentationSitePartName, Type = typeof(ContentControl))]
[TemplatePart(Name = CurrentContentPresentationSitePartName, Type = typeof(ContentControl))]
public class TransitioningContentControl : ContentControl
{
#region Visual state names
/// <summary>
/// The name of the group that holds the presentation states.
/// </summary>
private const string PresentationGroup = "PresentationStates"; /// <summary>
/// The name of the state that represents a normal situation where no
/// transition is currently being used.
/// </summary>
private const string NormalState = "Normal"; /// <summary>
/// The name of the state that represents the default transition.
/// </summary>
public const string DefaultTransitionState = "DefaultTransition";
#endregion Visual state names #region Template part names
/// <summary>
/// The name of the control that will display the previous content.
/// </summary>
internal const string PreviousContentPresentationSitePartName = "PreviousContentPresentationSite"; /// <summary>
/// The name of the control that will display the current content.
/// </summary>
internal const string CurrentContentPresentationSitePartName = "CurrentContentPresentationSite"; #endregion Template part names #region TemplateParts
/// <summary>
/// Gets or sets the current content presentation site.
/// </summary>
/// <value>The current content presentation site.</value>
private ContentPresenter CurrentContentPresentationSite { get; set; } /// <summary>
/// Gets or sets the previous content presentation site.
/// </summary>
/// <value>The previous content presentation site.</value>
private ContentPresenter PreviousContentPresentationSite { get; set; }
#endregion TemplateParts #region public bool IsTransitioning /// <summary>
/// Indicates whether the control allows writing IsTransitioning.
/// </summary>
private bool _allowIsTransitioningWrite; /// <summary>
/// Gets a value indicating whether this instance is currently performing
/// a transition.
/// </summary>
public bool IsTransitioning
{
get { return (bool)GetValue(IsTransitioningProperty); }
private set
{
_allowIsTransitioningWrite = true;
SetValue(IsTransitioningProperty, value);
_allowIsTransitioningWrite = false;
}
} /// <summary>
/// Identifies the IsTransitioning dependency property.
/// </summary>
public static readonly DependencyProperty IsTransitioningProperty =
DependencyProperty.Register(
"IsTransitioning",
typeof(bool),
typeof(TransitioningContentControl),
new PropertyMetadata(OnIsTransitioningPropertyChanged)); /// <summary>
/// IsTransitioningProperty property changed handler.
/// </summary>
/// <param name="d">TransitioningContentControl that changed its IsTransitioning.</param>
/// <param name="e">Event arguments.</param>
private static void OnIsTransitioningPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TransitioningContentControl source = (TransitioningContentControl)d; if (!source._allowIsTransitioningWrite)
{
source.IsTransitioning = (bool)e.OldValue;
throw new InvalidOperationException("TransitiotioningContentControl_IsTransitioningReadOnly");
}
}
#endregion public bool IsTransitioning /// <summary>
/// The storyboard that is used to transition old and new content.
/// </summary>
private Storyboard _currentTransition; /// <summary>
/// Gets or sets the storyboard that is used to transition old and new content.
/// </summary>
private Storyboard CurrentTransition
{
get { return _currentTransition; }
set
{
// decouple event
if (_currentTransition != null)
{
_currentTransition.Completed -= OnTransitionCompleted;
} _currentTransition = value; if (_currentTransition != null)
{
_currentTransition.Completed += OnTransitionCompleted;
}
}
} #region public string Transition
/// <summary>
/// Gets or sets the name of the transition to use. These correspond
/// directly to the VisualStates inside the PresentationStates group.
/// </summary>
public string Transition
{
get { return GetValue(TransitionProperty) as string; }
set { SetValue(TransitionProperty, value); }
} /// <summary>
/// Identifies the Transition dependency property.
/// </summary>
public static readonly DependencyProperty TransitionProperty =
DependencyProperty.Register(
"Transition",
typeof(string),
typeof(TransitioningContentControl),
new PropertyMetadata(DefaultTransitionState, OnTransitionPropertyChanged)); /// <summary>
/// TransitionProperty property changed handler.
/// </summary>
/// <param name="d">TransitioningContentControl that changed its Transition.</param>
/// <param name="e">Event arguments.</param>
private static void OnTransitionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TransitioningContentControl source = (TransitioningContentControl)d;
string oldTransition = e.OldValue as string;
string newTransition = e.NewValue as string; if (source.IsTransitioning)
{
source.AbortTransition();
} // find new transition
Storyboard newStoryboard = source.GetStoryboard(newTransition); // unable to find the transition.
if (newStoryboard == null)
{
// could be during initialization of xaml that presentationgroups was not yet defined
if (VisualStates.TryGetVisualStateGroup(source, PresentationGroup) == null)
{
// will delay check
source.CurrentTransition = null;
}
else
{
// revert to old value
source.SetValue(TransitionProperty, oldTransition); throw new ArgumentException(
"TransitioningContentControl_TransitionNotFound");
}
}
else
{
source.CurrentTransition = newStoryboard;
}
}
#endregion public string Transition #region public bool RestartTransitionOnContentChange
/// <summary>
/// Gets or sets a value indicating whether the current transition
/// will be aborted when setting new content during a transition.
/// </summary>
public bool RestartTransitionOnContentChange
{
get { return (bool)GetValue(RestartTransitionOnContentChangeProperty); }
set { SetValue(RestartTransitionOnContentChangeProperty, value); }
} /// <summary>
/// Identifies the RestartTransitionOnContentChange dependency property.
/// </summary>
public static readonly DependencyProperty RestartTransitionOnContentChangeProperty =
DependencyProperty.Register(
"RestartTransitionOnContentChange",
typeof(bool),
typeof(TransitioningContentControl),
new PropertyMetadata(false, OnRestartTransitionOnContentChangePropertyChanged)); /// <summary>
/// RestartTransitionOnContentChangeProperty property changed handler.
/// </summary>
/// <param name="d">TransitioningContentControl that changed its RestartTransitionOnContentChange.</param>
/// <param name="e">Event arguments.</param>
private static void OnRestartTransitionOnContentChangePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((TransitioningContentControl)d).OnRestartTransitionOnContentChangeChanged((bool)e.OldValue, (bool)e.NewValue);
} /// <summary>
/// Called when the RestartTransitionOnContentChangeProperty changes.
/// </summary>
/// <param name="oldValue">The old value of RestartTransitionOnContentChange.</param>
/// <param name="newValue">The new value of RestartTransitionOnContentChange.</param>
protected virtual void OnRestartTransitionOnContentChangeChanged(bool oldValue, bool newValue)
{
}
#endregion public bool RestartTransitionOnContentChange #region Events
/// <summary>
/// Occurs when the current transition has completed.
/// </summary>
public event RoutedEventHandler TransitionCompleted;
#endregion Events /// <summary>
/// Initializes a new instance of the <see cref="TransitioningContentControl"/> class.
/// </summary>
public TransitioningContentControl()
{
DefaultStyleKey = typeof(TransitioningContentControl);
} /// <summary>
/// Builds the visual tree for the TransitioningContentControl control
/// when a new template is applied.
/// </summary>
public override void OnApplyTemplate()
{
if (IsTransitioning)
{
AbortTransition();
} base.OnApplyTemplate(); PreviousContentPresentationSite = GetTemplateChild(PreviousContentPresentationSitePartName) as ContentPresenter;
CurrentContentPresentationSite = GetTemplateChild(CurrentContentPresentationSitePartName) as ContentPresenter; if (CurrentContentPresentationSite != null)
{
CurrentContentPresentationSite.Content = Content;
} // hookup currenttransition
Storyboard transition = GetStoryboard(Transition);
CurrentTransition = transition;
if (transition == null)
{
string invalidTransition = Transition;
// revert to default
Transition = DefaultTransitionState; throw new ArgumentException(
"TransitioningContentControl_TransitionNotFound");
} VisualStateManager.GoToState(this, NormalState, false);
VisualStateManager.GoToState(this, Transition, true);
} /// <summary>
/// Called when the value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property changes.
/// </summary>
/// <param name="oldContent">The old value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property.</param>
/// <param name="newContent">The new value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property.</param>
protected override void OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent); StartTransition(oldContent, newContent);
} /// <summary>
/// Starts the transition.
/// </summary>
/// <param name="oldContent">The old content.</param>
/// <param name="newContent">The new content.</param>
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "newContent", Justification = "Should be used in the future.")]
private void StartTransition(object oldContent, object newContent)
{
// both presenters must be available, otherwise a transition is useless.
if (CurrentContentPresentationSite != null && PreviousContentPresentationSite != null)
{
CurrentContentPresentationSite.Content = newContent; PreviousContentPresentationSite.Content = oldContent; // and start a new transition
if (!IsTransitioning || RestartTransitionOnContentChange)
{
IsTransitioning = true;
VisualStateManager.GoToState(this, NormalState, false);
VisualStateManager.GoToState(this, Transition, true);
}
}
} /// <summary>
/// Handles the Completed event of the transition storyboard.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnTransitionCompleted(object sender, EventArgs e)
{
AbortTransition(); RoutedEventHandler handler = TransitionCompleted;
if (handler != null)
{
handler(this, new RoutedEventArgs());
}
} /// <summary>
/// Aborts the transition and releases the previous content.
/// </summary>
public void AbortTransition()
{
// go to normal state and release our hold on the old content.
VisualStateManager.GoToState(this, NormalState, false);
IsTransitioning = false;
if (PreviousContentPresentationSite != null)
{
PreviousContentPresentationSite.Content = null;
}
} /// <summary>
/// Attempts to find a storyboard that matches the newTransition name.
/// </summary>
/// <param name="newTransition">The new transition.</param>
/// <returns>A storyboard or null, if no storyboard was found.</returns>
private Storyboard GetStoryboard(string newTransition)
{
VisualStateGroup presentationGroup = VisualStates.TryGetVisualStateGroup(this, PresentationGroup);
Storyboard newStoryboard = null;
if (presentationGroup != null)
{
newStoryboard = presentationGroup.States
.OfType<VisualState>()
.Where(state => state.Name == newTransition)
.Select(state => state.Storyboard)
.FirstOrDefault();
}
return newStoryboard;
} }
}

5. CustomWindow

此处原来有关于CustomWindow的一些注释,但是经验证,注释有误,故贴代码时将注释删除了。

using System;
using System.Windows;
using System.Windows.Input; namespace stonemqy.CustomWindow.Main
{
public class CustomWindow : Window
{
public CustomWindow()
{
DefaultStyleKey = typeof(CustomWindow);
CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow, CanResizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, MinimizeWindow, CanMinimizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, RestoreWindow, CanResizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
} protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (e.ButtonState == MouseButtonState.Pressed)
DragMove();
} protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (SizeToContent == SizeToContent.WidthAndHeight)
InvalidateMeasure();
} #region Window Commands private void CanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip;
} private void CanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ResizeMode != ResizeMode.NoResize;
} private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
//SystemCommands.CloseWindow(this);
} private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MaximizeWindow(this);
} private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MinimizeWindow(this);
} private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.RestoreWindow(this);
} private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
{
var element = e.OriginalSource as FrameworkElement;
if (element == null)
return; var point = WindowState == WindowState.Maximized ? new Point(, element.ActualHeight)
: new Point(Left + BorderThickness.Left, element.ActualHeight + Top + BorderThickness.Top);
point = element.TransformToAncestor(this).Transform(point);
SystemCommands.ShowSystemMenu(this, point);
} #endregion
}
}

6. Generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:stonemqy.CustomWindow.Main"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"> <DataTemplate x:Key="RestoreWhite">
<Grid UseLayoutRounding="True"
RenderTransform="1,0,0,1,.5,.5">
<Path Data="M2,0 L8,0 L8,6 M0,3 L6,3 M0,2 L6,2 L6,8 L0,8 Z"
Width="8"
Height="8"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="White"
StrokeThickness="1" />
</Grid>
</DataTemplate> <DataTemplate x:Key="CloseWhite">
<Grid Margin="1,0,0,0"> <Rectangle Stroke="White"
Height="2"
RenderTransformOrigin="0.5,0.5"
Width="11"
UseLayoutRounding="True">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="45" />
<TranslateTransform />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Stroke="White"
Height="2"
RenderTransformOrigin="0.5,0.5"
Width="11"
UseLayoutRounding="True">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="-45" />
<TranslateTransform />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</DataTemplate> <DataTemplate x:Key="MaximizeWhite">
<Grid>
<Path Data="M0,1 L9,1 L9,8 L0,8 Z"
Width="9"
Height="8"
Margin="0,2,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="White"
StrokeThickness="2" />
</Grid>
</DataTemplate> <DataTemplate x:Key="MinimizeWhite">
<Grid>
<Path Data="M0,6 L8,6 Z"
Width="8"
Height="7"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stroke="White"
StrokeThickness="2" />
</Grid>
</DataTemplate> <Style x:Key="TitleBarButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2"
SnapsToDevicePixels="True"
Stroke="Transparent"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <Style x:Key="TitleBarButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="Focusable"
Value="False" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Padding"
Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="LayoutRoot">
<Rectangle x:Name="ButtonBackground"
Width="28"
Height="28"
Fill="#FFFFFFFF"
Opacity="0" />
<Border x:Name="ButtonBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<ContentPresenter x:Name="TitleBarButtonContentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid> <ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Opacity"
Value="0.2"
TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsPressed"
Value="True">
<Setter Property="Opacity"
Value="0.4"
TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="TitleBarButtonContentPresenter"
Property="Opacity"
Value=".5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--<Style TargetType="{x:Type local:OmecWindow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:OmecWindow}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>--> <Style TargetType="{x:Type local:CustomWindow}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background"
Value="#FFF1F1F1" />
<Setter Property="BorderBrush"
Value="#FF0874AA" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="ResizeMode"
Value="CanResizeWithGrip" />
<Setter Property="UseLayoutRounding"
Value="True" />
<Setter Property="TextOptions.TextFormattingMode"
Value="Display" />
<Setter Property="WindowStyle"
Value="SingleBorderWindow" />
<Setter Property="FontFamily"
Value="Segoe UI" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CornerRadius="0"
GlassFrameThickness="1"
UseAeroCaptionButtons="False"
NonClientFrameEdges="None" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomWindow}"> <Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
x:Name="WindowBorder">
<Grid x:Name="LayoutRoot"
Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> <Grid x:Name="PART_WindowTitleGrid"
Grid.Row="0"
Height="26.4"
Background="{TemplateBinding BorderBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<!--<Image Source="{TemplateBinding Icon}"
Margin="7,0,5,0"
VerticalAlignment="Center"
/>-->
<Button VerticalAlignment="Center"
Margin="7,0,5,0"
Content="{TemplateBinding Icon}"
Height="{x:Static SystemParameters.SmallIconHeight}"
Width="{x:Static SystemParameters.SmallIconWidth}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsTabStop="False">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Image Source="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{x:Static SystemCommands.ShowSystemMenuCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{x:Static SystemCommands.CloseWindowCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<ContentControl IsTabStop="False"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{DynamicResource {x:Static SystemFonts.CaptionFontSize}}"
Content="{TemplateBinding Title}" />
</StackPanel>
<StackPanel x:Name="WindowCommandButtonsStackPanel"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="Transparent"
Orientation="Horizontal"
WindowChrome.IsHitTestVisibleInChrome="True">
<Button x:Name="Minimize"
ToolTip="Minimize"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}"
ContentTemplate="{StaticResource MinimizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
<Grid Margin="1,0,1,0">
<Button x:Name="Restore"
ToolTip="Restore"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}"
ContentTemplate="{StaticResource RestoreWhite}"
Style="{StaticResource TitleBarButtonStyle}"
Visibility="Collapsed"
IsTabStop="False" />
<Button x:Name="Maximize"
ToolTip="Maximize"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}"
ContentTemplate="{StaticResource MaximizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</Grid>
<Button x:Name="Close"
ToolTip="Close"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}"
ContentTemplate="{StaticResource CloseWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</StackPanel>
</Grid>
<AdornerDecorator Grid.Row="1" KeyboardNavigation.IsTabStop="False">
<!--<ContentPresenter x:Name="MainContentPresenter"
KeyboardNavigation.TabNavigation="Cycle" />-->
<local:TransitioningContentControl Content="{TemplateBinding Content}"
x:Name="MainContentPresenter" KeyboardNavigation.TabNavigation="Cycle" />
</AdornerDecorator>
<ResizeGrip x:Name="ResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Grid.Row="1"
IsTabStop="False"
Visibility="Hidden"
WindowChrome.ResizeGripDirection="BottomRight" />
</Grid>
</Border> <ControlTemplate.Triggers>
<Trigger Property="IsActive"
Value="False">
<Setter Property="BorderBrush"
Value="#FF6F7785" />
</Trigger>
<Trigger Property="WindowState"
Value="Maximized">
<Setter TargetName="Maximize"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Visible" />
<Setter TargetName="LayoutRoot"
Property="Margin"
Value="7" />
</Trigger>
<Trigger Property="WindowState"
Value="Normal">
<Setter TargetName="Maximize"
Property="Visibility"
Value="Visible" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<Trigger Property="ResizeMode"
Value="NoResize">
<Setter TargetName="Minimize"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="Maximize"
Property="Visibility"
Value="Collapsed" />
<Setter TargetName="Restore"
Property="Visibility"
Value="Collapsed" />
</Trigger> <MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode"
Value="CanResizeWithGrip" />
<Condition Property="WindowState"
Value="Normal" />
</MultiTrigger.Conditions>
<Setter TargetName="ResizeGrip"
Property="Visibility"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter> </Style> <Style TargetType="local:TransitioningContentControl">
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Stretch" />
<Setter Property="Transition"
Value="DefaultTransition" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TransitioningContentControl">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PresentationStates">
<VisualState x:Name="DefaultTransition">
<Storyboard>
<!--<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0"/>
</DoubleAnimationUsingKeyFrames>-->
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.400"
Value="1" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimation BeginTime="00:00:00"
Duration="00:00:00.500"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
From="50"
To="0">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.100"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState> <VisualState x:Name="UpTransition">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="1" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="30" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="0" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="0" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="-30" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState> <VisualState x:Name="DownTransition">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="1" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="CurrentContentPresentationSite"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="-40" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="0" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="0" />
</DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="PreviousContentPresentationSite"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00"
Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300"
Value="40" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState> </VisualStateGroup>
</VisualStateManager.VisualStateGroups> <Grid>
<ContentPresenter x:Name="PreviousContentPresentationSite"
Content="{x:Null}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter> <ContentPresenter x:Name="CurrentContentPresentationSite"
Content="{x:Null}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

7. MainWindow.xaml

<local:CustomWindow x:Class="stonemqy.CustomWindow.Main.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:stonemqy.CustomWindow.Main"
Title="MainWindow" Height="350" Width="525">
<Grid> </Grid>
</local:CustomWindow>

8. MainWindow.cs

namespace stonemqy.CustomWindow.Main
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : CustomWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}

9. 运行效果

WPF自定义Window样式(1)

10. 项目代码

源码

WPF自定义Window样式(1)的更多相关文章

  1. WPF自定义Window样式(2)

    1. 引言 在上一篇中,介绍了如何建立自定义窗体.接下来,我们需要考虑将该自定义窗体基类放到类库中去,只有放到类库中,我们才能在其他地方去方便的引用该基类. 2. 创建类库 接上一篇的项目,先添加一个 ...

  2. WPF 自定义ComboBox样式,自定义多选控件

    原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...

  3. WPF 自定义MenuItem样式

    原文:WPF 自定义MenuItem样式 一.前言 默认的MenuItem样式比较普通,这次自定义MenuItem的样式也只是对MenuItem的颜色风格进行变化.需要其他功能的变化,大家可以根据样式 ...

  4. WPF自定义TabControl样式

    WPF自定义TabControl,TabControl美化 XAML代码: <TabControl x:Class="SunCreate.Common.Controls.TabCont ...

  5. WPF 自定义滚动条样式

    先看一下效果: 先分析一下滚动条有哪儿几部分组成: 滚动条总共有五部分组成: 两端的箭头按钮,实际类型为RepeatButton Thumb 两端的空白,实际也是RepeatButton 最后就是Th ...

  6. WPF自定义Window窗体样式

    资源文件代码: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation ...

  7. WPF&colon;自定义Metro样式文件夹选择对话框FolderBrowserDialog

    1.前言 WPF并没有文件选择对话框,要用也就只有使用Winform版的控件.至今我也没有寻找到一个WPF版本的文件选择对话框. 可能是我眼浊,如果各位知道有功能比较健全的WPF版文件选择对话框.文件 ...

  8. WPF 自定义CheckBox样式

    自定义CheckBox样式,mark一下,方便以后参考复用 设计介绍: 1.一般CheckBox模板太难看了,肯定要重写其中的模板 2.模板状态为未选中状态和选中状态,设置为默认未选中就好了. 默认状 ...

  9. WPF 自定义ComboBox样式

    一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样式效果: 基本样式代码如下: <!--ComboBo ...

随机推荐

  1. PCA算法是怎么跟协方差矩阵&sol;特征值&sol;特征向量勾搭起来的&quest;

    PCA, Principle Component Analysis, 主成份分析, 是使用最广泛的降维算法. ...... (关于PCA的算法步骤和应用场景随便一搜就能找到了, 所以这里就不说了. ) ...

  2. silverlight 报 System&period;NullReferenceException 未将对象引用设置到对象的实例。

    在 Microsoft.Windows.Design.Platform.SilverlightMetadataContext.SilverlightXamlExtensionImplementatio ...

  3. 解决Execwb 导致 ado崩溃的问题。

    http://qc.embarcadero.com/wc/qcmain.aspx?d=61255

  4. C&num;定义委托函数实现在别的窗体中操作主窗体中的SerialPort控件

    1.在主窗体(含有serialPort的窗体)中 //先定义委托 public delegate void OpenPort(); public delegate void ClosePort(); ...

  5. 分布式事务实现-Spanner

    Spanner要满足的external consistency 是指:后开始的事务一定可以看到先提交的事务的修改.所有事务的读写都加锁可以解决这个问题,缺点是性能较差.特别是对于一些workload中 ...

  6. &lbrack;DeeplearningAI笔记&rsqb;ML strategy&lowbar;1&lowbar;1正交化&sol;单一数字评估指标

    机器学习策略 ML strategy 觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.1 什么是ML策略 机器学习策略简介 情景模拟 假设你正在训练一个分类器,你的系统已经达到了90%准确 ...

  7. 寻找DevExpress破解经历之旅

    众所周知DevExpress是收费的,但是破解版的也不少,近期公司需要做发票套打的功能让我找个打印工具,我寻思着DevExpress这个软件好像挺不错的,功能强大,看了下价格方面,好吧!2W多呢,市面 ...

  8. java中的stream的泛型方法的使用示例

    本文章使用jdk8测试 ,并结合使用lambda测试 测试前准备一些测试数据: class ObjectDemo { private Integer id; private String name; ...

  9. nginx 编译安装时的编译参数说明(不建议看)

    https://www.cnblogs.com/wazy/p/8108824.html ./configure --user=www \ #worker进程运行用户 --group=www \ #wo ...

  10. JavaScript数据类型-2---Undefined、 Null、 Boolean、 Number、 String&period;

    学习目标 1.掌握JavaScript的数据类型 2.掌握typeof操作符 3.掌握Undefined 4.掌握null JavaScript的数据类型 ECMAScript中有5种简单数据类型(也 ...