WPF自定义基本窗口类和样式

时间:2017-08-10 19:55:44

标签: c# wpf mvvm resourcedictionary

我有一个可以打开许多窗口的应用程序,我希望所有窗口看起来都一样。我正在覆盖默认的Windows窗口chrome样式并制作我自己的样式,因此任何打开的新窗口(不包括消息框)都应该具有相同的窗口样式。但是,无论我似乎尝试它都行不通。我可以使用一个窗口来使用它,但是当我想使它成为一种全局样式时,它总是崩溃或者根本不能正常工作。

这是我的代码:

WindowBaseStyle.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MyProject.Styles"
                    xmlns:views="clr-namespace:Myproject.Views">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="GlobalStyles.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="{x:Type views:WindowBase}" BasedOn="{StaticResource {x:Type Window}}">
        <Setter Property="AllowsTransparency" Value="False" />
        <Setter Property="BorderBrush" Value="Red" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="WindowState" Value="Normal" />
        <Setter Property="WindowStyle" Value="SingleBorderWindow" />
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CaptionHeight="30"
                              UseAeroCaptionButtons="False"/>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type views:WindowBase}">
                    <Border BorderBrush="Blue" BorderThickness="1" SnapsToDevicePixels="True">
                    <DockPanel Background="White" LastChildFill="True" >
                        <Grid Background="Blue" DockPanel.Dock="Top">
                            <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" VerticalAlignment="Center">
                                <Button Name="PART_SystemMenuButton" Command="{Binding MenuCommand}" Style="{DynamicResource SystemIconButton}">
                                    <Image Height="16" Width="16" Source="/Resources/icon.png" Stretch="Fill"/>
                                </Button>
                                <Viewbox Height="16" HorizontalAlignment="Stretch" Margin="14,2,0,0" >
                                    <TextBlock FontSize="12" Foreground="White" Text="{Binding Title,RelativeSource={RelativeSource FindAncestor,AncestorType=Window}}" />
                                </Viewbox>
                            </StackPanel>
                                <StackPanel Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
                                    <Button x:Name="PART_MinimizeButton" Command="{Binding MinimizeCommand}" Height="30" Margin="0,0,0,0" ToolTip="Minimize" Width="45">
                                        <Image Source="/Resources/minimize.png" Stretch="None" />
                                        <Button.Style>
                                            <Style TargetType="{x:Type Button}">
                                                <Setter Property="Background" Value="#0079CB" />
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type Button}">
                                                            <Border Background="{TemplateBinding Background}">
                                                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                                            </Border>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter Property="Background" Value="#64AEEC"/>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Button.Style>
                                    </Button>
                                    <Button x:Name="PART_MaximizeButton" Command="{Binding MaximizeCommand}" Height="30" Margin="0,0,0,0" Width="45">
                                        <Image>
                                            <Image.Style>
                                                <Style TargetType="{x:Type Image}">
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Normal">
                                                            <Setter Property="Source" Value="/Resources/maximize.png" />
                                                            <Setter Property="Stretch" Value="None" />
                                                        </DataTrigger>
                                                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximized">
                                                            <Setter Property="Source" Value="/Resources/unmaximize.png" />
                                                            <Setter Property="Stretch" Value="None" />
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Image.Style>
                                        </Image>
                                        <Button.Style>
                                            <Style TargetType="{x:Type Button}">
                                                <Setter Property="Background" Value="#0079CB" />
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type Button}">
                                                            <Border Background="{TemplateBinding Background}">
                                                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                                            </Border>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter Property="Background" Value="#64AEEC"/>
                                                    </Trigger>
                                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Normal">
                                                        <Setter Property="ToolTip" Value="Maximize" />
                                                    </DataTrigger>
                                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximized">
                                                        <Setter Property="ToolTip" Value="Restore Down" />
                                                    </DataTrigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Button.Style>
                                    </Button>
                                    <Button x:Name="PART_CloseButton" Command="{Binding CloseCommand}" Height="30" Margin="0,0,0,0" ToolTip="Close" Width="45" >
                                        <Image Source="/Resources/close.png" Stretch="None" />
                                        <Button.Style>
                                            <Style TargetType="{x:Type Button}">
                                                <Setter Property="Background" Value="#0079CB" />
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type Button}">
                                                            <Border Background="{TemplateBinding Background}">
                                                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                                            </Border>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter Property="Background" Value="Red"/>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </Button.Style>
                                    </Button>
                                </StackPanel>
                            </StackPanel>
                        </Grid>
                        <!-- this ContentPresenter automatically binds to the content of the window -->
                        <ContentPresenter />
                    </DockPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

WindowBase.cs

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;

namespace MyProject.Views
{
    [TemplatePart(Name = "PART_MinimizeButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_MaximizeButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_CloseButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_SystemMenuButton", Type = typeof(Button))]
    public class WindowBase: Window
    {
        static WindowBase()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomWindow), new FrameworkPropertyMetadata(typeof(CustomWindow)));
        }

        public WindowBase()
        {
            Loaded += (sender, evnt) =>
            {
                var MinimizeButton = (Button)Template.FindName("PART_MinimizeButton", this);
                var MaximizeButton = (Button)Template.FindName("PART_MaximizeButton", this);
                var CloseButton = (Button)Template.FindName("PART_CloseButton", this);
                var SystemMenuButton = (Button)Template.FindName("PART_SystemMenuButton", this);

                MinimizeButton.Click += (s, e) => WindowState = WindowState.Minimized;
                MaximizeButton.Click += (s, e) => WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
                CloseButton.Click += (s, e) => Close();
                SystemMenuButton.Click += (s, e) => SystemCommands.ShowSystemMenu(this, GetMousePosition());
            };
        }
    }
}

Window1.xaml

<local:WindowBase x:Class="MyProject.Views.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyProject.Views"
        Height="750"
        Width="1125">
    <Grid>
    </Grid>
</local:WindowBase>

Window1.xaml.cs

using System.Windows;

namespace MyProject.Views
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1: WindowBase
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}    

我总体上遵循MVVM模式,并且大部分来自我在网上看过的所有文章和视频,他们都遵循这个基本方法,他们说这一切都有效,但我似乎无法得到它上班。

另外需要注意的是,每当我将自定义窗口控件添加到Window1.xaml文件时,它会破坏设计器并说它是“无效标记”

另请注意,我将“WindowBaseStyle”资源字典作为合并资源字典添加到App.xaml文件中。

非常感谢任何帮助!!谢谢

0 个答案:

没有答案