How to create a Windows 8-style application bar in WPF?

I intended to create an application for Windows 8 styles (Metro), but found out that there is no support for using the dual screen, which is a requirement for my application.

Now I am redesigning my application as a desktop application in WPF. But I still like to imitate some of the nice design features from Windows 8 apps.

One of the design features is the outputs commonly used in the style of Windows 8:

  • Bottom command bar
  • Top navigation bar
  • A right spell that is common to all applications

The general scheme that they all have is a pop-up temporary panel that overlays on top of the current window layout.

My question is: how can I create something like this in WPF?

I have no problem creating a main grid with a hidden bottom line that becomes visible to display some common command buttons. But it would be nice if it flew over my standard layout, rather than squeezing it.

I know that you can open a new window on top of the current one, but this creates a bad code design and it is difficult to get a beautiful look. I would rather do it in the same window.

+4
source share
1 answer

Cool question! I actually did the spell quite recently.

ideally you need something like

<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> 

Now, instead of compressing the contents, the Overlay grid will be on top of it, looking like a charm panel! all with xaml

If you have more questions about this, give me a scream!

Change my implementation of Charm - feel free to use it for exaggeration!

 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 } 

The little trick I found was to set the opacity to 0 when it was not expanded, but set the width to 10, this allows the user to place the mouse on the side of the screen and then it will appear after the second or so .. amuses.

Change - as requested .. 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; } } 
+11
source

Source: https://habr.com/ru/post/1441544/


All Articles