如何在WPF中创建Windows 8样式应用程序栏



我打算创建一个Windows 8样式应用程序(Metro),但发现没有支持使用双屏幕,这是我应用的需求。

现在,我将应用程序重新设计为WPF中的桌面应用程序。但是我仍然喜欢模仿Windows 8应用程序中的一些不错的设计功能。

设计功能之一是通常在Windows 8样式应用中使用的飞行条:

  • 命令的底部应用程序栏
  • 顶级导航栏
  • 所有应用程序常见的正确魅力

他们的设计共同是一个临时飞行面板,该面板位于当前窗口布局的顶部。

我的问题是:如何在WPF中创建类似的东西?

我没有问题来创建一个带有隐藏底部行的主网格,该网格可见以显示一些常见的命令按钮。但是,很高兴将其飞出我的标准布局,而不是挤压。

我知道可以在当前顶部打开一个新窗口,但这会产生不良的代码设计,并且很难看起来很漂亮。我更喜欢在同一窗口中进行。

很酷的问题!我实际上最近做了魅力栏。

理想情况下,您需要的就是

<Grid x:Name="LayoutRoot">
 <Grid x:Name="Overlay" Panel.ZIndex="1000" Visibility="Collapsed">
    <!-- This is where your slide out control is going to go -->
  </Grid>
  <!-- Use whatever layout you need -->
  <ContentControl x:Name="MainContent" />
</Grid>

现在而不是挤压内容 - 覆盖网格将与魅力栏相似!全部与xaml

如果您对此有疑问,请大喊!

编辑;我的魅力实施 - 随时使用用于Inspriation!

public class SlidePanel : ContentControl
    {
        static SlidePanel()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SlidePanel), new FrameworkPropertyMetadata(typeof(SlidePanel)));
        }
        public SlidePanel()
        {
            EventManager.RegisterClassHandler(typeof(SlidePanel), SlidePanel.MouseEnterEvent,
                                              new RoutedEventHandler(OnLocalMouseEnter));
            EventManager.RegisterClassHandler(typeof(SlidePanel), SlidePanel.MouseLeaveEvent,
                                              new RoutedEventHandler(OnLocalMouseLeave));
        }
        #region Mouse Handlers
        private static void OnLocalMouseEnter(object sender, RoutedEventArgs e)
        {
            SetExpanded(sender, true);
        }
        private static void OnLocalMouseLeave(object sender, RoutedEventArgs e)
        {
            SetExpanded(sender, false);
        }
        private static void SetExpanded(object sender, bool expanded)
        {
            SlidePanel panel = sender as SlidePanel;
            if (panel != null)
            {
                panel.IsExpanded = expanded;
            }
        }
        #endregion Mouse Handlers
        #region Panel Width
        public double PanelWidth
        {
            get { return (double)GetValue(PanelWidthProperty); }
            set { SetValue(PanelWidthProperty, value); }
        }
        // Using a DependencyProperty as the backing store for PanelWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PanelWidthProperty =
            DependencyProperty.Register("PanelWidth", typeof(double), typeof(SlidePanel), new UIPropertyMetadata(5.0));
        #endregion Panel Width
        #region Closed Width
        public double ClosedWidth
        {
            get { return (double)GetValue(ClosedWidthProperty); }
            set { SetValue(ClosedWidthProperty, value); }
        }
        // Using a DependencyProperty as the backing store for ClosedWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ClosedWidthProperty =
            DependencyProperty.Register("ClosedWidth", typeof(double), typeof(SlidePanel), new UIPropertyMetadata(5.0, new PropertyChangedCallback(OnClosedWidthChange)));
        #endregion Closed Width
        #region Expanded Property
        public bool IsExpanded
        {
            get { return (bool)GetValue(IsExpandedProperty); }
            set { SetValue(IsExpandedProperty, value); }
        }
        // Using a DependencyProperty as the backing store for IsExpanded.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsExpandedProperty =
            DependencyProperty.Register("IsExpanded", typeof(bool), typeof(SlidePanel), new UIPropertyMetadata(false, new PropertyChangedCallback(OnExpandedChanged)));

        #endregion Expanded Property
        #region Property Changes
        private static void OnExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == e.OldValue)
                return;
            SlidePanel panel = d as SlidePanel;
            if (panel == null)
                return;
            bool newVal = (bool)e.NewValue;
            panel.IsExpanded = newVal;
            bool expanded = (bool)panel.GetValue(IsExpandedProperty);
            Storyboard widthAnimation = AnimationHelper.CreateDoubleAnimation<SlidePanel>(panel, expanded,
                (p, a) =>
                {
                    a.From = (double)p.GetValue(SlidePanel.ClosedWidthProperty);
                    a.To = (double)p.GetValue(SlidePanel.PanelWidthProperty);
                },
                (p, a) =>
                {
                    a.From = (double)p.GetValue(SlidePanel.WidthProperty);
                    a.To = (double)p.GetValue(SlidePanel.ClosedWidthProperty);
                }, new TimeSpan(0, 0, 0, 0, 300), WidthProperty);
            Timeline opacity = AnimationHelper.DoubleAnimation(0.0, 1.0, expanded,
                                                                      new TimeSpan(0, 0, 0, 0, 300), OpacityProperty);
            Storyboard.SetTargetName(opacity, panel.Name);
            Storyboard.SetTargetProperty(opacity, new PropertyPath(OpacityProperty));
            widthAnimation.Children.Add(opacity);
            widthAnimation.Begin(panel);
        }
        private static void OnClosedWidthChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            SlidePanel panel = d as SlidePanel;
            if (panel != null)
                panel.Width = (double)e.NewValue;
        }
        #endregion Property Changes
    }

我发现的一个小技巧是将不透明度设置为0时将其设置为0,但将宽度设置为10,然后允许用户将鼠标放在屏幕的侧面,然后在第二秒钟后出现。或者..欢呼。

编辑 - 根据要求.. AnimationHelper。

  public class AnimationHelper
    {
        public static Timeline DoubleAnimation(double from, double to, bool modifier, TimeSpan duration, DependencyProperty property)
        {
            DoubleAnimation animation = new DoubleAnimation();
            if (modifier)
            {
                animation.From = from;
                animation.To = to;
            }
            else
            {
                animation.To = from;
                animation.From = to;
            }
            animation.Duration = new Duration(duration);
            return animation;
        }
        public static Storyboard CreateDoubleAnimation<T>(T control, bool modifier, double from, double to, TimeSpan duration, DependencyProperty property) where T : Control
        {
            return
             AnimationHelper.CreateDoubleAnimation<T>(control, modifier,
                (p, a) =>
                {
                    a.From = from;
                    a.To = to;
                },
                (p, a) =>
                {
                    a.From = to;
                    a.To = from;
                }, duration, property);
        }
        public static Storyboard CreateDoubleAnimation<T>(T control, bool modifier, Action<T, DoubleAnimation> onTrue, Action<T, DoubleAnimation> onFalse, TimeSpan duration, DependencyProperty property) where T : Control
        {
            if (control == null)
                throw new ArgumentNullException("control");
            DoubleAnimation panelAnimation = new DoubleAnimation();
            if (modifier)
            {
                if (onTrue != null)
                    onTrue.Invoke(control, panelAnimation);
            }
            else
            {
                if (onFalse != null)
                    onFalse.Invoke(control, panelAnimation);
            }

            panelAnimation.Duration = new Duration(duration);
            Storyboard sb = new Storyboard();
            Storyboard.SetTargetName(panelAnimation, control.Name);
            Storyboard.SetTargetProperty(panelAnimation, new PropertyPath(property));
            sb.Children.Add(panelAnimation);
            return sb;
        }
    }

最新更新