Inside the AppBar Control

,

AppBar is a custom ItemsControl that wraps a Microsoft.Phone.Shell.ApplicationBar. As it is an ItemsControl, it enables you to add buttons and menu items to it, either in code or in XAML, in a manner not unlike the built-in ApplicationBar.

When the AppBar control is first loaded, it sets the host page’s ApplicationBar to its own ApplicationBar field.

The AppBar.Build method is used to populate the ApplicationBar and is called in the following situations:

Image When its Loaded event is raised

Image When its collection of buttons or menu items changes

Image When a button or menu item’s visibility changes

The Build method calls the BuildAux method and prevents cycles from occurring while building is taking place, as shown:

bool building;

void Build()
{
    if (building)
    {
        return;
    }

    try
    {
        building = true;
        BuildAux();
    }

    finally
    {
        building = false;
    }
}

After requesting notification of button and menu item visibility changes, discussed in a moment, the Build method collects the members of its ItemCollection and, depending on their type, adds them to the ApplicationBar’s Buttons or MenuItems collection (see Listing 8.4).

LISTING 8.4. AppBar.BuildAux Method


void BuildAux()
{
    applicationBar.Buttons.Clear();
    applicationBar.MenuItems.Clear();

    foreach (FrameworkElement item in Items.OfType<FrameworkElement>())
    {
        RegisterForNotification("Visibility", item);
    }

    var buttonList = (from button in Items.Where(notUIElementOrVisibleFunc)
                                .OfType<IApplicationBarIconButtonProvider>()
                        select button.Button).ToList();

    if (buttonList.Count > 4)
    {
        buttonList = buttonList.Take(4).ToList();
    }

    applicationBar.Buttons.AddRange(buttonList);

    var menuItemList = (from item in Items.Where(notUIElementOrVisibleFunc)

                        .OfType<IApplicationBarMenuItemProvider>()
                        select item.MenuItem).ToList();

    applicationBar.MenuItems.AddRange(menuItemList);
}


Two classes, AppBarIconButtonBase and AppBarMenuItemBase, provide an extensibility point that allows you to create your own custom application bar buttons or menu items. If they do not suit your needs, however, you can opt to implement IApplicationBarIconButtonProvider and IApplicationBarMenuItemProvider instead.

The task of the custom AppBar items, such as the AppBarIconButton and the AppBarMenuItem, is to wrap an instance of the corresponding built-in ApplicationBarIconButton or ApplicationBarMenuItem, and to expose the wrapped item’s properties as dependency properties.

Both IApplicationBarIconButtonProvider and IApplicationBarMenuItemProvider have a single property that is used to retrieve the actual ApplicationBarIconButton or ApplicationBarMenuItem.

During population of the ApplicationBar’s Buttons and MenuItems properties within the AppBar.BuildAux method, a Func named notUIElementOrVisibleFunc is used to determine the visibility of an item, as shown:

readonly Func<object, bool> notUIElementOrVisibleFunc
    = x =>
    {
        var element = x as UIElement;
        return element == null || element.Visibility == Visibility.Visible;
    };

Monitoring Item Visibility

No built-in event exists to monitor the Visibility property of UIElements. Therefore, to be notified when a button or menu item’s visibility changes, we rely on an attached property and a custom AppBar method called RegisterForNotification, which uses a Binding to listen for button and menu item visibility changes. See the following excerpt:

void RegisterForNotification(
    string propertyName,
    FrameworkElement element)
{
    BindingExpression expression
         = element.GetBindingExpression(ItemVisibilityProperty);
    if (expression == null)
    {
        Binding binding = new Binding(propertyName) { Source = element };
        element.SetBinding(ItemVisibilityProperty, binding);
    }
}

Extending the Icon and Menu Item Base Classes

AppBarHyperlinkButton subclasses AppBarIconButtonBase to provide support for page navigation and navigation to external resources (see Listing 8.5).

When the base class’s Click event is raised, the PhoneApplicationFrame navigates to the NavigateUri property. If the Uri is an external resource, the WebBrowserTask is used instead.

LISTING 8.5. AppBarHyperlinkButton Class


public class AppBarHyperlinkButton : AppBarIconButtonBase
{
    public static readonly DependencyProperty NavigateUriProperty
        = DependencyProperty.RegisterAttached(
            "NavigateUri",
            typeof(Uri),
            typeof(AppBarHyperlinkButton),
            null);

    public Uri NavigateUri
    {
        get
        {
            return (Uri)GetValue(NavigateUriProperty);
        }
        set
        {
            SetValue(NavigateUriProperty, value);
        }
    }

    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        Navigate();
    }

    void Navigate()
    {
        Uri uri = NavigateUri;
        if (uri == null)
        {
            return;
        }

        if (uri.IsAbsoluteUri)
        {
            WebBrowserTask task = new WebBrowserTask { Uri = uri };
            task.Show();
            return;
        }

        var frame = Application.Current.RootVisual as PhoneApplicationFrame;
        if (frame == null)
        {
            return;
        }

        frame.Navigate(uri);
    }
}


Several AppBar items are in the downloadable sample code, which you are free to use in your own code. If you spend time using the built-in ApplicationBar I am certain you will appreciate the benefits of wrapping it in a more developer friendly class like the AppBar.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.7