2013-07-25 108 views
5

是否有人将MahApps.Metro样式应用于NavigationWindow?我已经为一个Window实现了它,但是需要将它应用于带有Pages的NavigationWindow。我尝试过扩展NavigationWindow并像MetroWindow那样添加修改,但没有运气。窗口有一个标准的标题栏和边框,内容完全是黑色的。将MahApps.Metro样式应用于NavigationWindow

using System; 
using System.Windows; 
using System.Windows.Input; 
using System.Windows.Interop; 
using System.Windows.Media; 
using System.Windows.Navigation; 
using MahApps.Metro.Native; 

namespace MahApps.Metro.Controls 
{ 
    [TemplatePart(Name = PART_TitleBar, Type = typeof(UIElement))] 
    [TemplatePart(Name = PART_WindowCommands, Type = typeof(WindowCommands))] 
    public class MetroNavigationWindow : NavigationWindow 
    { 
     private const string PART_TitleBar = "PART_TitleBar"; 
     private const string PART_WindowCommands = "PART_WindowCommands"; 

     public static readonly DependencyProperty ShowIconOnTitleBarProperty = DependencyProperty.Register("ShowIconOnTitleBar", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty ShowTitleBarProperty = DependencyProperty.Register("ShowTitleBar", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty ShowMinButtonProperty = DependencyProperty.Register("ShowMinButton", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty ShowMaxRestoreButtonProperty = DependencyProperty.Register("ShowMaxRestoreButton", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty TitlebarHeightProperty = DependencyProperty.Register("TitlebarHeight", typeof(int), typeof(MetroNavigationWindow), new PropertyMetadata(30)); 
     public static readonly DependencyProperty TitleCapsProperty = DependencyProperty.Register("TitleCaps", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 
     public static readonly DependencyProperty SaveWindowPositionProperty = DependencyProperty.Register("SaveWindowPosition", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(false)); 
     public static readonly DependencyProperty WindowPlacementSettingsProperty = DependencyProperty.Register("WindowPlacementSettings", typeof(IWindowPlacementSettings), typeof(MetroNavigationWindow), new PropertyMetadata(null)); 
     public static readonly DependencyProperty TitleForegroundProperty = DependencyProperty.Register("TitleForeground", typeof(Brush), typeof(MetroNavigationWindow)); 
     public static readonly DependencyProperty IgnoreTaskbarOnMaximizeProperty = DependencyProperty.Register("IgnoreTaskbarOnMaximize", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(false)); 
     public static readonly DependencyProperty GlowBrushProperty = DependencyProperty.Register("GlowBrush", typeof(SolidColorBrush), typeof(MetroNavigationWindow), new PropertyMetadata(null)); 
     public static readonly DependencyProperty FlyoutsProperty = DependencyProperty.Register("Flyouts", typeof(FlyoutsControl), typeof(MetroNavigationWindow), new PropertyMetadata(null)); 
     public static readonly DependencyProperty WindowTransitionsEnabledProperty = DependencyProperty.Register("WindowTransitionsEnabled", typeof(bool), typeof(MetroNavigationWindow), new PropertyMetadata(true)); 

     bool isDragging; 

     public bool WindowTransitionsEnabled 
     { 
      get { return (bool)this.GetValue(WindowTransitionsEnabledProperty); } 
      set { SetValue(WindowTransitionsEnabledProperty, value); } 
     } 

     public FlyoutsControl Flyouts 
     { 
      get { return (FlyoutsControl)GetValue(FlyoutsProperty); } 
      set { SetValue(FlyoutsProperty, value); } 
     } 

     public WindowCommands WindowCommands { get; set; } 

     public bool IgnoreTaskbarOnMaximize 
     { 
      get { return (bool)this.GetValue(IgnoreTaskbarOnMaximizeProperty); } 
      set { SetValue(IgnoreTaskbarOnMaximizeProperty, value); } 
     } 

     public Brush TitleForeground 
     { 
      get { return (Brush)GetValue(TitleForegroundProperty); } 
      set { SetValue(TitleForegroundProperty, value); } 
     } 

     public bool SaveWindowPosition 
     { 
      get { return (bool)GetValue(SaveWindowPositionProperty); } 
      set { SetValue(SaveWindowPositionProperty, value); } 
     } 

     public IWindowPlacementSettings WindowPlacementSettings 
     { 
      get { return (IWindowPlacementSettings)GetValue(WindowPlacementSettingsProperty); } 
      set { SetValue(WindowPlacementSettingsProperty, value); } 
     } 

     public bool ShowIconOnTitleBar 
     { 
      get { return (bool)GetValue(ShowIconOnTitleBarProperty); } 
      set { SetValue(ShowIconOnTitleBarProperty, value); } 
     } 

     public bool ShowTitleBar 
     { 
      get { return (bool)GetValue(ShowTitleBarProperty); } 
      set { SetValue(ShowTitleBarProperty, value); } 
     } 

     public bool ShowMinButton 
     { 
      get { return (bool)GetValue(ShowMinButtonProperty); } 
      set { SetValue(ShowMinButtonProperty, value); } 
     } 

     public bool ShowCloseButton 
     { 
      get { return (bool)GetValue(ShowCloseButtonProperty); } 
      set { SetValue(ShowCloseButtonProperty, value); } 
     } 

     public int TitlebarHeight 
     { 
      get { return (int)GetValue(TitlebarHeightProperty); } 
      set { SetValue(TitlebarHeightProperty, value); } 
     } 

     public bool ShowMaxRestoreButton 
     { 
      get { return (bool)GetValue(ShowMaxRestoreButtonProperty); } 
      set { SetValue(ShowMaxRestoreButtonProperty, value); } 
     } 

     public bool TitleCaps 
     { 
      get { return (bool)GetValue(TitleCapsProperty); } 
      set { SetValue(TitleCapsProperty, value); } 
     } 

     public SolidColorBrush GlowBrush 
     { 
      get { return (SolidColorBrush)GetValue(GlowBrushProperty); } 
      set { SetValue(GlowBrushProperty, value); } 
     } 

     public string WindowTitle 
     { 
      get { return TitleCaps ? Title.ToUpper() : Title; } 
     } 

     public MetroNavigationWindow() 
     { 
      Loaded += this.MetroWindow_Loaded; 
     } 

     private void MetroWindow_Loaded(object sender, RoutedEventArgs e) 
     { 
      VisualStateManager.GoToState(this, "AfterLoaded", true); 

      if (!ShowTitleBar) 
      { 
       //Disables the system menu for reasons other than clicking an invisible titlebar. 
       IntPtr handle = new WindowInteropHelper(this).Handle; 
       UnsafeNativeMethods.SetWindowLong(handle, UnsafeNativeMethods.GWL_STYLE, UnsafeNativeMethods.GetWindowLong(handle, UnsafeNativeMethods.GWL_STYLE) & ~UnsafeNativeMethods.WS_SYSMENU); 
      } 

      if (this.Flyouts == null) 
      { 
       this.Flyouts = new FlyoutsControl(); 
      } 
     } 

     static MetroNavigationWindow() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(MetroNavigationWindow), new FrameworkPropertyMetadata(typeof(MetroNavigationWindow))); 
     } 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 

      if (WindowCommands == null) 
       WindowCommands = new WindowCommands(); 

      var titleBar = GetTemplateChild(PART_TitleBar) as UIElement; 

      if (ShowTitleBar && titleBar != null) 
      { 
       titleBar.MouseDown += TitleBarMouseDown; 
       titleBar.MouseUp += TitleBarMouseUp; 
       titleBar.MouseMove += TitleBarMouseMove; 
      } 
      else 
      { 
       MouseDown += TitleBarMouseDown; 
       MouseUp += TitleBarMouseUp; 
       MouseMove += TitleBarMouseMove; 
      } 
     } 

     protected override void OnStateChanged(EventArgs e) 
     { 
      if (WindowCommands != null) 
      { 
       WindowCommands.RefreshMaximiseIconState(); 
      } 

      base.OnStateChanged(e); 
     } 

     protected void TitleBarMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      var mousePosition = e.GetPosition(this); 
      bool isIconClick = ShowIconOnTitleBar && mousePosition.X <= TitlebarHeight && mousePosition.Y <= TitlebarHeight; 

      if (e.ChangedButton == MouseButton.Left) 
      { 
       if (isIconClick) 
       { 
        if (e.ClickCount == 2) 
        { 
         Close(); 
        } 
        else 
        { 
         ShowSystemMenuPhysicalCoordinates(this, PointToScreen(new Point(0, TitlebarHeight))); 
        } 
       } 
       else 
       { 
        IntPtr windowHandle = new WindowInteropHelper(this).Handle; 
        UnsafeNativeMethods.ReleaseCapture(); 

        var wpfPoint = PointToScreen(Mouse.GetPosition(this)); 
        short x = Convert.ToInt16(wpfPoint.X); 
        short y = Convert.ToInt16(wpfPoint.Y); 

        int lParam = x | (y << 16); 

        UnsafeNativeMethods.SendMessage(windowHandle, Constants.WM_NCLBUTTONDOWN, Constants.HT_CAPTION, lParam); 
        if (e.ClickCount == 2 && (ResizeMode == ResizeMode.CanResizeWithGrip || ResizeMode == ResizeMode.CanResize)) 
        { 
         WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; 
        } 
       } 
      } 
      else if (e.ChangedButton == MouseButton.Right) 
      { 
       ShowSystemMenuPhysicalCoordinates(this, PointToScreen(mousePosition)); 
      } 
     } 

     protected void TitleBarMouseUp(object sender, MouseButtonEventArgs e) 
     { 
      isDragging = false; 
     } 

     private void TitleBarMouseMove(object sender, MouseEventArgs e) 
     { 
      if (e.LeftButton != MouseButtonState.Pressed) 
      { 
       isDragging = false; 
      } 

      if (isDragging 
       && WindowState == WindowState.Maximized 
       && ResizeMode != ResizeMode.NoResize) 
      { 
       // Calculating correct left coordinate for multi-screen system. 
       Point mouseAbsolute = PointToScreen(Mouse.GetPosition(this)); 
       double width = RestoreBounds.Width; 
       double left = mouseAbsolute.X - width/2; 

       // Check if the mouse is at the top of the screen if TitleBar is not visible 
       if (!ShowTitleBar && mouseAbsolute.Y > TitlebarHeight) 
        return; 

       // Aligning window's position to fit the screen. 
       double virtualScreenWidth = SystemParameters.VirtualScreenWidth; 
       left = left + width > virtualScreenWidth ? virtualScreenWidth - width : left; 

       var mousePosition = e.MouseDevice.GetPosition(this); 

       // When dragging the window down at the very top of the border, 
       // move the window a bit upwards to avoid showing the resize handle as soon as the mouse button is released 
       Top = mousePosition.Y < 5 ? -5 : mouseAbsolute.Y - mousePosition.Y; 
       Left = left; 

       // Restore window to normal state. 
       WindowState = WindowState.Normal; 
      } 
     } 

     internal T GetPart<T>(string name) where T : DependencyObject 
     { 
      return (T)GetTemplateChild(name); 
     } 

     private static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation) 
     { 
      if (window == null) return; 

      var hwnd = new WindowInteropHelper(window).Handle; 
      if (hwnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(hwnd)) 
       return; 

      var hmenu = UnsafeNativeMethods.GetSystemMenu(hwnd, false); 

      var cmd = UnsafeNativeMethods.TrackPopupMenuEx(hmenu, Constants.TPM_LEFTBUTTON | Constants.TPM_RETURNCMD, (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero); 
      if (0 != cmd) 
       UnsafeNativeMethods.PostMessage(hwnd, Constants.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero); 
     } 
    } 
} 

回答

8

要,我使用的是MetroWindow作为我的主要浏览窗口,并MetroWindow它处理导航内的Frame做到这一点。

导航窗口

<Controls:MetroWindow x:Class="TestWpfApplicationMahApps.Metro.NavWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" Title="NavWindow" Height="300" Width="300"> 
    <Window.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" /> 
       <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" /> 
       <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> 
       <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" /> 
       <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Window.Resources> 
    <Frame Source="Page1.xaml" NavigationUIVisibility="Hidden"></Frame> 
</Controls:MetroWindow> 

这让我不会改变任何导航逻辑的,它可以从NavigationService就像它使用NavigationWindow时被调用。

1的.cs

/// <summary> 
/// Interaction logic for Page1.xaml 
/// </summary> 
public partial class Page1 : Page 
{ 
    public Page1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     NavigationService.Navigate(new Page2()); 
    } 
} 
+0

我不得不放弃帧的名称,即:<帧x:名称= “_ mainFrame中” ......和导航代码更改为:_mainFrame.Navigate(新MyOtherPage());仍然很好的解决方案,特别是你想删除导航histroy控制用户界面.. – BENN1TH