locked
Xaml BottomAppBar AppBarButton and GridView inter-binding

    Question

  • I am trying to bind the BottomAppBar AppBarButton Visibility to a selection state of the GridView  on a xaml page. Like this:

    <AppBarButton Visibility="{Binding SelectedIndex, ElementName=MyGridView, Converter={StaticResource IndexToVisibility}}"/>

    I tried with SelectedItem (check for null) or SelectedIndex (check for -1) - no way!

    IndexToVisibility - converter checks SeletedIndex value if it's "< 0" the button Visibility is Collapsed, otherwise it's Visible.

    The idea is - no selection, no command available.

    It does not work, the converter is never triggered, no error on compilation, nor on run. What could be the solutions of this problem? Thanks in advance for any tip.

    Friday, November 28, 2014 9:19 AM

Answers

  • Sorry Alexandre, I misremembered the details.

    There isn't a way to use an ElementName binding from the appbar to elements on the page.

    Setting the DataContext to the page will allow binding to the page. This is the common case used for things like Command binding. You could expose a property on the page which returns visibility information based on the GridView's selections.

    Tuesday, December 02, 2014 1:38 AM
    Owner
  • Hello Rob,

    Thank you, it worked.

    Though, it's a pitty that ElementName may not be used, to avoid the code behind usage.

    I finished with the following:

    1) the xaml page sets the the DataContext :

    DataContext

    ="{BindingDefaultViewModel,RelativeSource={RelativeSourceSelf}}"

    and this DataContext is enherited by the AppBarButton(s) wrapping CommandBar of the AppBar (bottom in my case). So in the code behind I don't set CommandBar DataContext specifically.

    2) AppBarButtons' Visibility may be bound like this:

    Visibility

    ="{BindingHasSelectionToVisibility}"

    or

    Visibility

    ="{BindingitemGridViewSelectedIndex,Converter={StaticResourceIndexToVisibilityConverter}}"

    with Converter.

    3) Those/this bound element(s) are set to issue the notification on every AppBar openning:

               

    this.BottomCommandBar.Opened += (sender, e) =>

    {   

    this.DefaultViewModel["HasSelectionToVisibility"] = (itemGridView.SelectedIndex >= 0 ? Visibility.Visible : Visibility.Collapsed);

    this.DefaultViewModel["itemGridViewSelectedIndex"] = itemGridView.SelectedIndex;

    };

    It works.

    My idea was to avoid code behind and avoid SelectedIndex tracking explicitely the Grid itself tracks it. The problem is to pull the Grid into binding.

    Well, thank you again, for me, the issue may be closed.

    Tuesday, December 02, 2014 1:51 PM

All replies

  • Hi Alexander,

    Simply test with some codes, works perfectly.

    XAML:

        <Page.Resources>
            <local:IndexToVisibility x:Key="IndexToVisibility"></local:IndexToVisibility>
        </Page.Resources>
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            
            <AppBarButton Visibility="{Binding SelectedIndex, ElementName=MyGridView, Converter={StaticResource IndexToVisibility}}"/>
            <GridView x:Name="MyGridView" HorizontalAlignment="Left" Height="165" Margin="348,81,0,0" VerticalAlignment="Top" Width="437">
                <GridViewItem>asdasd</GridViewItem>
                <GridViewItem>asdasd</GridViewItem>
                <GridViewItem>asdasd</GridViewItem>
                <GridViewItem>asdasd</GridViewItem>
                <GridViewItem>asdasd</GridViewItem>
            </GridView>
    
    
    
        </Grid>

    CS:

        public class IndexToVisibility : IValueConverter
        {
    
            #region IValueConverter Members
    
            // Define the Convert method to change a DateTime object to 
            // a month string.
            public object Convert(object value, Type targetType,
                object parameter, string language)
            {
                // The value parameter is the data from the source object.
                if ((int)value > 0)
                {
                    return Visibility.Visible;
                }
                return Visibility.Collapsed;
            }
    
            // ConvertBack is not implemented for a OneWay binding.
            public object ConvertBack(object value, Type targetType,
                object parameter, string language)
            {
                throw new NotImplementedException();
            }
    
            #endregion
        }

    --James


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, December 01, 2014 4:29 AM
    Moderator
  • I will try out later today (when I have my dev machine with me) I remind there was something with buttons in the app bar and when the appbar gets closed its unloading the buttons.

    Microsoft Certified Solutions Developer - Windows Store Apps Using C#

    Monday, December 01, 2014 6:37 AM
  • The BottomAppBar isn't in the same namespace as the page and so cant see the GridView to bind to it. If you set the AppBar's DataContext explicitly the binding should work:

    async void BasicPage1_Loaded(object sender, RoutedEventArgs e)
    {
        bottomAppBar.DataContext = this;
    }

    Monday, December 01, 2014 8:15 AM
    Owner
  • Thank you James,

    Actually, the AppBarButton is Inside the

    <Page.BottomAppBar>

    <CommandBarx:Name="BottomCommandBar" >

    <CommandBar.PrimaryCommands>

    <

    AppBarButtonx:Uid="btDuplicate"x:Name="btDuplicate"Label="Duplicate"Click="btDuplicate_Click"Visibility="{BindingElementName=itemGridView,Path=SelectedIndex,Converter={StaticResourceIndexToVisibilityConverter}}" >

    I thought it could be a namesapce issue but passing through the page name (pageRoot) like this:

    Visibility

    ="{BindingitemGridView.SelectedIndex,Converter={StaticResourceIndexToVisibilityConverter},ElementName=pageRoot}"

    does not work!

    Monday, December 01, 2014 8:44 AM
  • Hello Rob,

    Does not worked for me!

    1) BottomAppBar does not have x:Name property. As the AppBarButton is inside a command bar I tried to name and get to DataContext of it : BottomCommandBar.DataContext = this;

    <Page.BottomAppBar>

    <CommandBarx:Name="BottomCommandBar" >

    this does not worked.

    2) Getting the DataContext of the BottomAppBar neither worked:

               

    if(Window.Current.Content isFrame)

    {

    varframe = (Frame)Window.Current.Content;

    if(frame.Content isPage)

    {

    varpage = (Page)frame.Content;

    if(page.BottomAppBar != null)

    {

    page.BottomAppBar.DataContext = this;

    }

    }

    }

    3) Tring to use page name as a shared namespace - does nothing!

    Visibility

    ="{Binding MyGridView.SelectedIndex,Converter={StaticResourceIndexToVisibilityConverter},ElementName=pageRoot}"

    Monday, December 01, 2014 9:05 AM
  • Sorry Alexandre, I misremembered the details.

    There isn't a way to use an ElementName binding from the appbar to elements on the page.

    Setting the DataContext to the page will allow binding to the page. This is the common case used for things like Command binding. You could expose a property on the page which returns visibility information based on the GridView's selections.

    Tuesday, December 02, 2014 1:38 AM
    Owner
  • Hello Rob,

    Thank you, it worked.

    Though, it's a pitty that ElementName may not be used, to avoid the code behind usage.

    I finished with the following:

    1) the xaml page sets the the DataContext :

    DataContext

    ="{BindingDefaultViewModel,RelativeSource={RelativeSourceSelf}}"

    and this DataContext is enherited by the AppBarButton(s) wrapping CommandBar of the AppBar (bottom in my case). So in the code behind I don't set CommandBar DataContext specifically.

    2) AppBarButtons' Visibility may be bound like this:

    Visibility

    ="{BindingHasSelectionToVisibility}"

    or

    Visibility

    ="{BindingitemGridViewSelectedIndex,Converter={StaticResourceIndexToVisibilityConverter}}"

    with Converter.

    3) Those/this bound element(s) are set to issue the notification on every AppBar openning:

               

    this.BottomCommandBar.Opened += (sender, e) =>

    {   

    this.DefaultViewModel["HasSelectionToVisibility"] = (itemGridView.SelectedIndex >= 0 ? Visibility.Visible : Visibility.Collapsed);

    this.DefaultViewModel["itemGridViewSelectedIndex"] = itemGridView.SelectedIndex;

    };

    It works.

    My idea was to avoid code behind and avoid SelectedIndex tracking explicitely the Grid itself tracks it. The problem is to pull the Grid into binding.

    Well, thank you again, for me, the issue may be closed.

    Tuesday, December 02, 2014 1:51 PM