[Windows 8] Application bar popup button

Here is a small control to create an application bar button which will display a content in a popup when the button is clicked.

Visually it gives this

image

So how to create this? First you have to use the AppBarPopupButton control below.

 

namespace Indeed.Controls
{
    public class AppBarPopupButton : Button
    {
        public FrameworkElement PopupContent
        {
            get { return (FrameworkElement)GetValue(PopupContentProperty); }
            set { SetValue(PopupContentProperty, value); }
        }

        public static readonly DependencyProperty PopupContentProperty =
            DependencyProperty.Register("PopupContent", typeof(FrameworkElement), typeof(AppBarPopupButton), new PropertyMetadata(null, (o, e) => (o as AppBarPopupButton).CreatePopup()));

        private Popup popup;
        private SerialDisposable sizeChanged = new SerialDisposable();

        protected override void OnTapped(Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
        {
            base.OnTapped(e);

            if (popup != null)
            {
                var transform = this.TransformToVisual(Window.Current.Content);
                var offset = transform.TransformPoint(default(Point));

                sizeChanged.Disposable = PopupContent.ObserveSizeChanged().Do(_ => popup.VerticalOffset = offset.Y - (PopupContent.ActualHeight + 20)).Subscribe();

                popup.HorizontalOffset = offset.X + 24;

                popup.DataContext = this.DataContext;
                popup.IsOpen = true;
            }
        }

        private void CreatePopup()
        {
            popup = new Popup { IsLightDismissEnabled = true };
            popup.Closed += (o, e) => this.GetParentOfType<AppBar>().IsOpen = false;

            popup.ChildTransitions = new Windows.UI.Xaml.Media.Animation.TransitionCollection();
            popup.ChildTransitions.Add(new Windows.UI.Xaml.Media.Animation.PopupThemeTransition());

            var container = new Grid();            
            container.Children.Add(PopupContent);

            popup.Child = container;
        }
    }
}

The ObserveSizeChanged method is just an extension method which observe the SizeChanged event (using Reactive Extensions - Rx-Metro package in Nuget). If you’re not familiar with Rx, you can replace this line (and the SerialDisposable stuff) by a simple subscription to the SizeChanged event (using +=) but don’t forget to unsubscribe to it !

public static IObservable<Unit> ObserveSizeChanged(this FrameworkElement element)
{
    return Observable.FromEventPattern<SizeChangedEventHandler, SizeChangedEventArgs>(
                            o => element.SizeChanged += o,
                            o => element.SizeChanged -= o)
                        .Select(_ => Unit.Default);
}

The GetParentOfType extension method just retrieve the first parent of type (it’s a common extension method that every Windows 8 developer should have created !).

You can of course tweak to control (for example if you want to center the content to the button or anything else) to fit your needs.

How to use this control? It’s very simple, in an AppBar control just add it and define the PopupContent property.

<ic:AppBarPopupButton Style="{StaticResource RefreshAppBarButtonStyle}" HorizontalAlignment="Left">
    <ic:AppBarPopupButton.PopupContent>
        <Grid>
            [...]
        </Grid>
    </ic:AppBarPopupButton.PopupContent>
</ic:AppBarPopupButton>

When the button is clicked the popup is displayed. When the popup is closed, the app bar is closed too.

I hope this will help you !

No Comments