11

My goal is to only have an AppBar available under a certain circumstance. I am attempting to accomplish this by creating an AppBar, but leaving it disabled until that circumstance arises. However, if you set the IsEnabled attribute on an AppBar to False, when you launch your app and right-click (which typically opens the AppBar), the application crashes. Is this a bug in the framework? What is the proper way to disable an AppBar?

EDIT: It also occurs when you set Visibility to Collapsed.

More info: I am running it through the Visual Studio debugger, but a separate "Visual Studio Just-In-Time Debugger" window is popping up with the message "An unhandled win32 exception occurred in App.exe [2596]." A warning box pops up on top of that that says "A debugger is attached to App.exe but not configured to debug this unhandled exception. To debug this exception, detach the current debugger."

EDIT 2: It's not just my code. It also crashes if you just add IsEnabled="False" to the AppBar in Microsoft's own sample AppBarControl project (found here: http://code.msdn.microsoft.com/windowsapps/XAML-AppBar-control-sample-2aa1cbb4)

EDIT 3: @G. Andrew Duthie - devhammer provided the answer I am using. I just wanted to add that I found that it is best to use this.BottomAppBar = null to disable it as opposed to setting the IsEnabled or Visibility properties. If you just set Visibility to Collapsed, then when you right-click, the app still thinks an AppBar is present even though it isn't visible, so your next regular click will be interpreted as the click that typically dismisses the AppBar, so you'll have to click a second time to actually carry out the action you were attempting.

jokeefe
  • 1,836
  • 4
  • 22
  • 27
  • 3
    What does "the application crashes" mean? Does it crash in the framework? In your code? Do you have a callstack? Is an exception thrown? What is the exception (and message)? – James McNellis Aug 14 '12 at 18:37
  • I think it's crashing in the framework. I am running it through the Visual Studio debugger, but a separate "Visual Studio Just-In-Time Debugger" window is popping up with the message "An unhandled win32 exception occurred in App.exe [2596]." A warning box pops up on top of that that says "A debugger is attached to App.exe but not configured to debug this unhandled exception. To debug this exception, detach the current debugger." – jokeefe Aug 14 '12 at 18:46
  • I think we need more context to spot the problem. Can you post your AppBar xaml? – N_A Aug 14 '12 at 19:05
  • You could wait a couple of days and see if the release version of Windows 8 throws an exception too – Emond Aug 14 '12 at 19:14
  • 1
    @mydogisbox It's not just my code. It also crashes if you just add `IsEnabled="False"` to the AppBar in Microsoft's own sample AppBarControl project (found here: http://code.msdn.microsoft.com/windowsapps/XAML-AppBar-control-sample-2aa1cbb4) – jokeefe Aug 14 '12 at 19:28

5 Answers5

8

I've been playing with this for a bit (using both IsEnabled, as well as setting the Visibility property to Visibility.Collapsed), and the only way I could successfully disable the AppBar without raising the exception was to show the AppBar first. Once the AppBar has been shown, setting IsEnabled to false, or setting Visibility to Visibility.Collapsed no longer throws the exception.

However, if you create the AppBar programmatically, like so:

myAppBar = new AppBar();
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
Button myButton = new Button();
myButton.Content = "Click Me";
sp.Children.Add(myButton);
myAppBar.Content = sp;

but don't add it to Page.BottomAppBar until the first time you need it, you won't get the exception.

I tested using a button with the following handler:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    if (this.BottomAppBar == null)
    {
        this.BottomAppBar = myAppBar;
    }
    else {
        this.BottomAppBar = null;
    }
}

When the app loads the first time, if you attempt to invoke the AppBar, nothing happens. Click the button (which adds the AppBar to Page.BottomAppBar), and invoking the AppBar will show the AppBar. Click the button again, and the AppBar is no longer shown (though myAppBar is still instantiated and ready when you need it again).

Hope that helps!

devhammer
  • 1,384
  • 1
  • 8
  • 15
  • 1
    This work perfectly. Thank you! I found that it is best to use `this.BottomAppBar = null` to disable it as opposed to setting the `IsEnabled` or `Visibility` properties. If you just set `Visibility` to `Collapsed`, then when you right-click, the app still thinks an AppBar is present even though it isn't visible, so your next regular click will be interpreted as the click that typically dismisses the AppBar, so you'll have to click a second time to actually carry out the action you were attempting. Thanks again for the help! – jokeefe Aug 14 '12 at 20:13
  • Attempting to load an appbar resource object defined in a xaml file fails. However, I succeeded with using just raw code without any xaml resources. – Scott Nimrod Feb 13 '13 at 03:35
4

If you want to still want to define your AppBar in XAML, you can programmatically close the AppBar in the code behind. In XAML, create the bottom AppBar:

<Page.BottomAppBar>
    <AppBar Name="MyAppBar" Opened="AppBarOpened">
        ...
    </AppBar>
</Page.BottomAppBar>

Then, in the C# code behind:

private void AppBarOpened(object sender, object e)
{
    if ( CanAppBarOpen() == false)
    {
        MyAppBar.IsOpen = false;
    }
}

You'll have to implement your own check for "CanAppBarOpen()"

Rymac
  • 41
  • 1
2

You can use the CustomAppBar from the WinRT XAML Toolkit. It can be disabled in multiple ways -you can bind its CanOpen or CanDismiss properties to block it from appearing or going away, which might be what you want.

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
  • 1
    Of course it does. He/she wanted the appbar to work or not work depending on conditions and the CustomAppBar provides just that and it does not crash. I created it precisely due to the limitations of/problems with the native AppBar. – Filip Skakun Aug 14 '12 at 19:56
  • Thanks a lot for your suggestion, @Filip Skakun. If I wasn't able to get the solution G. Andrew Duthie - devhammer provided to work, I definitely would have gone this route. I'll check back with your library the next time I come across an issue like this. – jokeefe Aug 14 '12 at 20:20
2

You can do like this by handling opened event of AppBar

In XAML:

<Page.BottomAppbar>
   <AppBar IsEnabled="False" Visibility="Collapsed" Opened="bottomappbar_opened_event">
</Page.BottomAppbar>

In C# Code:

 private void bottomappbar_opened_event(object sender, object e)
 {
     if (!this.BottomAppBar.IsEnabled)
     {
         if (this.BottomAppBar.IsOpen)
         this.BottomAppBar.IsOpen = false;
     }
 }
Community
  • 1
  • 1
pashaplus
  • 3,596
  • 2
  • 26
  • 25
0

1. Add a selection changed event to your flipview control in the xaml file:

<FlipView SelectionChanged="MyFlipView_SelectionChanged" />

2. Add this class member variable to your xaml code-behind file:

Dictionary<object, Tuple<AppBar, AppBar>> _appbarDictionary = new Dictionary<object, Tuple<AppBar, AppBar>>();

3. Implement the FlipView's selection changed handler here:

private void MyFlipView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var flipView = sender as FlipView;

    BuildPageAppBarDictionary();

    InitializeAppBar(flipView);
    NullOtherAppBars(flipView);
}
  1. Add these methods:

    private void BuildPageAppBarDictionary() { _appbarDictionary.Clear();

    foreach (var item in MyFlipView.Items)
    {
        var page = item as Page;
        Tuple<AppBar, AppBar> appbars = new Tuple<AppBar, AppBar>(page.TopAppBar, page.BottomAppBar);
        _appbarDictionary.Add(page, appbars);
    }
    

    }

    private void InitializeAppBar(FlipView flipView) { if (_appbarDictionary.Count > 0) { var currentPage = flipView.SelectedItem as Page; currentPage.TopAppBar = _appbarDictionary[currentPage].Item1; currentPage.BottomAppBar = _appbarDictionary[currentPage].Item2;

        if (currentPage.TopAppBar != null)
        {
            currentPage.TopAppBar.IsEnabled = true;
        }
    
        if (currentPage.BottomAppBar != null)
        {
            currentPage.BottomAppBar.IsEnabled = true;
        }
    }
    

    }

    private void NullOtherAppBars(FlipView flipView) { foreach (var item in MyFlipView.Items) { if (item != flipView.SelectedItem) { var page = item as Page;

                page.TopAppBar = null;
                page.BottomAppBar = null;
            }
        }
    }
    

Please forgive the snippet formatting issues. I tried to make the example format to this page as best as I could.

Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118